当前位置: 首页 > news >正文

网站备案号图标上海网站开发一对一培训

网站备案号图标,上海网站开发一对一培训,网络搭建项目案例,wordpress错误怎么解决问题复现 在装配对象成员属性时#xff0c;我们常常会使用 Autowired 来装配。但是#xff0c;有时候我们也使用 Value 进行装配。不过这两种注解使用风格不同#xff0c;使用 Autowired 一般都不会设置属性值#xff0c;而 Value 必须指定一个字符串值#xff0c;因为其…问题复现 在装配对象成员属性时我们常常会使用 Autowired 来装配。但是有时候我们也使用 Value 进行装配。不过这两种注解使用风格不同使用 Autowired 一般都不会设置属性值而 Value 必须指定一个字符串值因为其定义做了要求定义代码如下public interface Value {/*** The actual value expression mdash; for example, code#{systemProperties.myProp}/code.*/String value();}另外在比较这两者的区别时我们一般都会因为 Value 常用于 String 类型的装配而误以为 Value 不能用于非内置对象的装配实际上这是一个常见的误区。例如我们可以使用下面这种方式来 Autowired 一个属性成员Value(#{student}) private Student student;其中 student 这个 Bean 定义如下Bean public Student student(){Student student createStudent(1, xie);return student; }当然正如前面提及我们使用 Value 更多是用来装配 String而且它支持多种强大的装配方式典型的方式参考下面的示例//注入正常字符串 Value(我是字符串) private String text; //注入系统参数、环境变量或者配置文件中的值 Value(${ip}) private String ip//注入其他Bean属性其中student为bean的IDname为其属性 Value(#{student.name}) private String name;上面我给你简单介绍了 Value 的强大功能以及它和 Autowired 的区别。那么在使用 Value 时可能会遇到那些错误呢这里分享一个最为典型的错误即使用 Value 可能会注入一个不是预期的值。我们可以模拟一个场景我们在配置文件 application.properties 配置了这样一个属性usernameadmin passwordpass然后我们在一个 Bean 中分别定义两个属性来引用它们RestController Slf4j public class ValueTestController {Value(${username})private String username;Value(${password})private String password;RequestMapping(path user, method RequestMethod.GET)public String getUser(){return username : password;}; }当我们去打印上述代码中的 username 和 password 时我们会发现 password 正确返回了但是 username 返回的并不是配置文件中指明的 admin而是运行这段程序的计算机用户名。很明显使用 Value 装配的值没有完全符合我们的预期。 案例解析 通过分析运行结果我们可以知道 Value 的使用方式应该是没有错的毕竟 password 这个字段装配上了但是为什么 username 没有生效成正确的值接下来我们就来具体解析下。我们首先了解下对于 ValueSpring 是如何根据 Value 来查询“值”的。我们可以先通过方法 DefaultListableBeanFactory#doResolveDependency 来了解 Value 的核心工作流程代码如下Nullable public Object doResolveDependency(DependencyDescriptor descriptor, Nullable String beanName,Nullable SetString autowiredBeanNames, Nullable TypeConverter typeConverter) throws BeansException {//省略其他非关键代码Class? type descriptor.getDependencyType();//寻找ValueObject value getAutowireCandidateResolver().getSuggestedValue(descriptor);if (value ! null) {if (value instanceof String) {//解析Value值String strVal resolveEmbeddedValue((String) value);BeanDefinition bd (beanName ! null containsBean(beanName) ?getMergedBeanDefinition(beanName) : null);value evaluateBeanDefinitionString(strVal, bd);}//转化Value解析的结果到装配的类型TypeConverter converter (typeConverter ! null ? typeConverter : getTypeConverter());try {return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());}catch (UnsupportedOperationException ex) {//异常处理}}//省略其他非关键代码}可以看到Value 的工作大体分为以下三个核心步骤。 寻找 value 在这步中主要是判断这个属性字段是否标记为 Value依据的方法参考 QualifierAnnotationAutowireCandidateResolver#findValueNullable protected Object findValue(Annotation[] annotationsToSearch) {if (annotationsToSearch.length 0) { AnnotationAttributes attr AnnotatedElementUtils.getMergedAnnotationAttributes(AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);//valueAnnotationType即为Valueif (attr ! null) {return extractValue(attr);}}return null; }解析 Value 的字符串值 如果一个字段标记了 Value则可以拿到对应的字符串值然后就可以根据字符串值去做解析最终解析的结果可能是一个字符串也可能是一个对象这取决于字符串怎么写。 将解析结果转化为要装配的对象的类型 当拿到第二步生成的结果后我们会发现可能和我们要装配的类型不匹配。假设我们定义的是 UUID而我们获取的结果是一个字符串那么这个时候就会根据目标类型来寻找转化器执行转化字符串到 UUID 的转化实际上发生在 UUIDEditor 中public class UUIDEditor extends PropertyEditorSupport {Overridepublic void setAsText(String text) throws IllegalArgumentException {if (StringUtils.hasText(text)) {//转化操作setValue(UUID.fromString(text.trim()));}else {setValue(null);}}//省略其他非关代码}通过对上面几个关键步骤的解析我们大体了解了 Value 的工作流程。结合我们的案例很明显问题应该发生在第二步即解析 Value 指定字符串过程执行过程参考下面的关键代码行String strVal resolveEmbeddedValue((String) value);这里其实是在解析嵌入的值实际上就是“替换占位符”工作。具体而言它采用的是 PropertySourcesPlaceholderConfigurer 根据 PropertySources 来替换。不过当使用 ${username} 来获取替换值时其最终执行的查找并不是局限在 application.property 文件中的。通过调试我们可以看到下面的这些“源”都是替换依据 [ConfigurationPropertySourcesPropertySource {nameconfigurationProperties}, StubPropertySource {nameservletConfigInitParams}, ServletContextPropertySource {nameservletContextInitParams}, PropertiesPropertySource {namesystemProperties}, OriginAwareSystemEnvironmentPropertySource {namesystemEnvironment}, RandomValuePropertySource {namerandom}, OriginTrackedMapPropertySource {nameapplicationConfig: classpath:/application.properties]}, MapPropertySource {namedevtools}]而具体的查找执行我们可以通过下面的代码PropertySourcesPropertyResolver#getProperty来获取它的执行方式Nullable protected T T getProperty(String key, ClassT targetValueType, boolean resolveNestedPlaceholders) {if (this.propertySources ! null) {for (PropertySource? propertySource : this.propertySources) {Object value propertySource.getProperty(key);if (value ! null) {//查到value即退出 return convertValueIfNecessary(value, targetValueType);}}}return null; }从这可以看出在解析 Value 字符串时其实是有顺序的查找的源是存在 CopyOnWriteArrayList 中在启动时就被有序固定下来一个一个“源”执行查找在其中一个源找到后就可以直接返回了。如果我们查看 systemEnvironment 这个源会发现刚好有一个 username 和我们是重合的且值不是 pass。 所以讲到这里你应该知道问题所在了吧这是一个误打误撞的例子刚好系统环境变量systemEnvironment中含有同名的配置。实际上对于系统参数systemProperties也是一样的这些参数或者变量都有很多如果我们没有意识到它的存在起了一个同名的字符串作为 Value 的值则很容易引发这类问题。 问题修正 针对这个案例有了源码的剖析我们就可以很快地找到解决方案了。例如我们可以避免使用同一个名称具体修改如下user.nameadmin user.passwordpass但是如果我们这么改的话其实还是不行的。实际上通过之前的调试方法我们可以找到类似的原因在 systemProperties 这个 PropertiesPropertySource 源中刚好存在 user.name真是无巧不成书。所以命名时我们一定要注意不仅要避免和环境变量冲突也要注意避免和系统变量等其他变量冲突这样才能从根本上解决这个问题。
http://www.hkea.cn/news/14378297/

相关文章:

  • 建设厅考试网站北京网站制作建设
  • 婚庆公司网站建设总结报告广州番禺天气
  • 做任务 网站网站设计模板 psd
  • 苏州网站排名建筑人才网证书查询
  • 网站开发 语言网页创意的再设计
  • 网站建设意见征求汇报开发利用水资源
  • 法语网站建设做任务的网站有哪些
  • 网站邮件设置厦门网站设计个人
  • 计算机网站建设论文总结什么是wap
  • 闲鱼怎么做钓鱼网站四川网站开发哪家好
  • js网站开发工具昆明网站seo服务
  • 三亚网站建设费用中国乐清网
  • 哪个做图网站可以挣钱wordpress编辑器添加字体大小
  • 广州建设培训网站wordpress后台导入数据库
  • 网站建设征求意见表网站制作项目分析怎么做 方法
  • 口碑好的网站开发公司域名怎么做网站内容
  • 雷山网站建设wordpress 用户密码加密
  • wordpress根据文章id显示内容苏州网站排名优化系统
  • 易迈互联网站建设怎么样网站建设 ui设计
  • 网站建设教程赚找湖南岚鸿认 可沈阳网站建设方案托管
  • 谷歌网站推广公司百度seo优化规则
  • 光谷做网站推广价格谷歌推广怎么做最有效
  • 辽宁省城乡住房和建设厅网站四川 网站建设
  • 网站底部放什么wordpress用户组名称
  • 汉堡只做网站国内做网站用的程序
  • 团购机票网站建设网站下载到本地
  • 做外贸怎样上国外网站安卓版傻瓜式编程app软件
  • 网站建设内容与实现功能wordpress优化搜索引擎
  • 做网站什么主题比较好装饰设计室内公司
  • 自己做网站前期困难吗站长资讯