前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java开发技术之Spring依赖注入知识学习

Java开发技术之Spring依赖注入知识学习

作者头像
用户1289394
发布2018-12-05 10:21:54
6030
发布2018-12-05 10:21:54
举报
文章被收录于专栏:Java学习网Java学习网

注入Bean的注解

@Autowired Spring提供的注解

不仅仅是对象,还有在构造器上,还能用在属性的Setter方法上。

不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属性设置为false。

将required属性设置为false时,Spring会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状态。但是,把required属性设置为false时,你需要谨慎对待。如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性有可能会出现NullPointerException。

@Inject注解来源于Java依赖注入规范,该规范同时还为我们定义了@Named注解。在自动装配中,Spring同时支持@Inject和@Autowired。尽管@Inject和@Autowired之间有着一些细微的差别,但是在大多数场景下,它们都是可以互相替换的。

@Autowired 是最常见的注解之一,但在老项目中,你可能会看到这些注解,它们的作用和@Autowired 相近:

  • @Inject 是JSR-330提供的注解
  • @Resource 是JSR-250提供的注解

条件化的Bean

假设你希望一个或多个bean只有在应用的类路径下包含特定的库时才创建。或者我们希望某个bean只有当另外某个特定的bean也声明了之后才会创建。我们还可能要求只有某个特定的环境变量设置之后,才会创建某个bean。

在Spring 4之前,很难实现这种级别的条件化配置,但是Spring 4引入了一个新的@Conditional注解,它可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。

通过ConditionContext,我们可以做到如下几点:

  • 借助getRegistry()返回的BeanDefinitionRegistry检查bean定义;
  • 借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在,甚至探查bean的属性;
  • 借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是什么;
  • 读取并探查getResourceLoader()返回的ResourceLoader所加载的资源;
  • 借助getClassLoader()返回的ClassLoader加载并检查类是否存在。

处理自动装配的歧义性

标示首选的bean

在声明bean的时候,通过将其中一个可选的bean设置为首选(primary)bean能够避免自动装配时的歧义性。当遇到歧义性的时候,Spring将会使用首选的bean,而不是其他可选的bean。实际上,你所声明就是“最喜欢”的bean。

限定自动装配的bean

设置首选bean的局限性在于@Primary无法将可选方案的范围限定到唯一一个无歧义性的选项中。它只能标示一个优先的可选方案。当首选bean的数量超过一个时,我们并没有其他的方法进一步缩小可选范围。

与之相反,Spring的限定符能够在所有可选的bean上进行缩小范围的操作,最终能够达到只有一个bean满足所规定的限制条件。如果将所有的限定符都用上后依然存在歧义性,那么你可以继续使用更多的限定符来缩小选择范围。

@Qualifier注解是使用限定符的主要方式。它可以与@Autowired和@Inject协同使用,在注入的时候指定想要注入进去的是哪个bean。例如,我们想要确保要将IceCream注入到setDessert()之中:

代码语言:javascript
复制
@Autowired@Qualifier("iceCream")public void setDessert(Dessert dessert){  this.dessert = dessert;
}

这是使用限定符的最简单的例子。为@Qualifier注解所设置的参数就是想要注入的bean的ID。所有使用@Component注解声明的类都会创建为bean,并且bean的ID为首字母变为小写的类名。因此,@Qualifier(“iceCream”)指向的是组件扫描时所创建的bean,并且这个bean是IceCream类的实例。

实际上,还有一点需要补充一下。更准确地讲,@Qualifier(“iceCream”)所引用的bean要具有String类型的“iceCream”作为限定符。如果没有指定其他的限定符的话,所有的bean都会给定一个默认的限定符,这个限定符与bean的ID相同。因此,框架会将具有“iceCream”限定符的bean注入到setDessert()方法中。这恰巧就是ID为iceCream的bean,它是IceCream类在组件扫描的时候创建的。

基于默认的bean ID作为限定符是非常简单的,但这有可能会引入一些问题。如果你重构了IceCream类,将其重命名为Gelato的话,那此时会发生什么情况呢?如果这样的话,bean的ID和默认的限定符会变为gelato,这就无法匹配setDessert()方法中的限定符。自动装配会失败。

这里的问题在于setDessert()方法上所指定的限定符与要注入的bean的名称是紧耦合的。对类名称的任意改动都会导致限定符失效。

SpringEL
  • Value实现资源的注入
Bean的初始化和销毁
  • Java配置方式:initMethod和destoryMethod
  • 注解:@PostConstruct和@PreDestory
Profile

提供在不同的环境下使用不同的配置

激活Profile

Spring在确定哪个profile处于激活状态时,需要依赖两个独立的属性:spring.profiles.active和spring.profiles.default。如果设置了spring.profiles.active属性的话,那么它的值就会用来确定哪个profile是激活的。但如果没有设置spring.profiles.active属性的话,那Spring将会查找spring.profiles.default的值。如果spring.profiles.active和spring.profiles.default均没有设置的话,那就没有激活的profile,因此只会创建那些没有定义在profile中的bean。

使用profile进行测试

当运行集成测试时,通常会希望采用与生产环境(或者是生产环境的部分子集)相同的配置进行测试。但是,如果配置中的bean定义在了profile中,那么在运行测试时,我们就需要有一种方式来启用合适的profile。

Spring提供了@ActiveProfiles注解,我们可以使用它来指定运行测试时要激活哪个profile。在集成测试时,通常想要激活的是开发环境的profile。

比如Profile(“dev”)

Application Event

使用Application Event可以做到Bean与Bean之间的通信

Spring的事件需要遵循如下流程:

  • 自定义事件,集成ApplicationEvent
  • 定义事件监听器,实现ApplicationListener
  • 使用容器发布事件
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java学习网 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 注入Bean的注解
    • @Autowired Spring提供的注解
    • 条件化的Bean
    • 处理自动装配的歧义性
      • 标示首选的bean
        • 限定自动装配的bean
          • SpringEL
            • Bean的初始化和销毁
              • Profile
                • 激活Profile
                • 使用profile进行测试
              • Application Event
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档