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

我不需要做网站海曙seo关键词优化方案

我不需要做网站,海曙seo关键词优化方案,济南建设网站企业报价,建设银行app问题复现 在装配对象成员属性时,我们常常会使用 Autowired 来装配。但是,有时候我们也使用 Value 进行装配。不过这两种注解使用风格不同,使用 Autowired 一般都不会设置属性值,而 Value 必须指定一个字符串值,因为其…

问题复现

  • 在装配对象成员属性时,我们常常会使用 @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的ID,name为其属性
    @Value("#{student.name}")
    private String name;
    
  • 上面我给你简单介绍了 @Value 的强大功能,以及它和 @Autowired 的区别。那么在使用 @Value 时可能会遇到那些错误呢?这里分享一个最为典型的错误,即使用 @Value 可能会注入一个不是预期的值。
  • 我们可以模拟一个场景,我们在配置文件 application.properties 配置了这样一个属性:
    username=admin
    password=pass
    
  • 然后我们在一个 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 没有生效成正确的值?接下来我们就来具体解析下。
  • 我们首先了解下对于 @Value,Spring 是如何根据 @Value 来查询“值”的。我们可以先通过方法 DefaultListableBeanFactory#doResolveDependency 来了解 @Value 的核心工作流程,代码如下:
    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> 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 的工作大体分为以下三个核心步骤。
  1. 寻找 @value
    • 在这步中,主要是判断这个属性字段是否标记为 @Value,依据的方法参考 QualifierAnnotationAutowireCandidateResolver#findValue:
      @Nullable
      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;
      }
      
  2. 解析 @Value 的字符串值
    • 如果一个字段标记了 @Value,则可以拿到对应的字符串值,然后就可以根据字符串值去做解析,最终解析的结果可能是一个字符串,也可能是一个对象,这取决于字符串怎么写。
  3. 将解析结果转化为要装配的对象的类型
    • 当拿到第二步生成的结果后,我们会发现可能和我们要装配的类型不匹配。假设我们定义的是 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 {name='configurationProperties'}, 
      StubPropertySource {name='servletConfigInitParams'}, ServletContextPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'},
      OriginTrackedMapPropertySource {name='applicationConfig: classpath:/application.properties]'},
      MapPropertySource {name='devtools'}]
      
    • 而具体的查找执行,我们可以通过下面的代码(PropertySourcesPropertyResolver#getProperty)来获取它的执行方式:
      @Nullable
      protected <T> T getProperty(String key, Class<T> 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.name=admin
    user.password=pass
    
  • 但是如果我们这么改的话,其实还是不行的。实际上,通过之前的调试方法,我们可以找到类似的原因,在 systemProperties 这个 PropertiesPropertySource 源中刚好存在 user.name,真是无巧不成书。所以命名时,我们一定要注意不仅要避免和环境变量冲突,也要注意避免和系统变量等其他变量冲突,这样才能从根本上解决这个问题。
http://www.yidumall.com/news/23139.html

相关文章:

  • 网站开发续签新网
  • 如何自己动手做网站欧美网站建设
  • 网站开发实验结论百度不让访问危险网站怎么办
  • 怎么免费做带音乐的网站网站怎么弄
  • 温州微网站制作公司推荐免费网络空间搜索引擎
  • wordpress媒体库加载不出来北京网站建设东轩seo
  • 独立做网站前端数据p2p万能搜索引擎
  • 网站开发专利营销推广的形式包括
  • 网站备案主办单位错误企业网站推广方法实验报告
  • wordpress集团网站国内搜索引擎大全
  • 网站交互怎么做原创文章代写平台
  • 博罗网站设计查收录
  • 济宁市做网站的公司网络优化工程师需要学什么
  • 苏州装修公司网站建设谷歌推广一年多少钱
  • 东莞 企业 网站制作全网整合营销公司
  • 衡水做网站电话sem推广优化
  • 做网站怎么赚钱 知乎如何做网站seo
  • 2017做哪些网站能致富微信附近人推广引流
  • 花蝴蝶免费视频在线观看高清版网站优化排名易下拉系统
  • 复旦学霸张立勇做的有关寺庙网站网络推广岗位职责和任职要求
  • wordpress替换百度站内搜索目前疫情最新情况
  • 如何建小企业网站外链查询工具
  • 网站改版意义企业建站系统
  • 做八年级题目的网站品牌运营管理有限公司
  • 国外那些网站是做五金批发福州网站优化
  • 怎样做自己的 优惠卷网站seo研究中心骗局
  • 做快递单的网站会不会是骗人的宁波seo关键词排名优化
  • 普陀做网站公司上海全网营销推广
  • 做cf网站最好用的系统优化软件
  • 互联网博客网站打开浏览器直接进入网站