《Spring》(十一) ---- 基于注解的依赖注入

  • @Autowired

@Autowired市按照类型匹配进行依赖注入的,它可以标注于类定义的多个位置:

  1. 域或属性
  2. 构造方法定义
  3. 方法定义  @Autowired不仅可以标注在传统的setter方法之上,而且还可以标注于任意名称的方法定义,只要该方法定义了需要被注入的参数就行。

为了给容器中定义的每个bean定义对应的实例注入依赖,需要遍历所有bean,然后通过反射,检查每个bean定义对应的类上各种可能位置上的@Autowired,如果存在,就可以从当前容器管理的对象中获取符合条件的对象,设置给@Autowired所标注的属性域/构造方法或方法定义。AutowiredAnnotationBeanPostProcessor是Spring提供的用于这个目的的BeanPostProcessor实现,所以只要在IoC容器的配置文件中追加

<bean class="org.springframework.beans.factory.annotation. 
AutowiredAnnotationBeanPostProcessor"/>

就可以让整个应用开始运作了。

  • @Qualifier

@Qualifier是byName自动绑定的注解版,IoC容器无法从多个同一类型的实例中选取我们真正想要的,那就用@Qualifier直接点名。

  • @Resource

IoC容器根据@Resource所制定的名称,到容器中查找beanName与之对应的实例,然后将查找到的对象实例注入给@Resource所标注的对象。例如

public class FXNewsProvider {
    @Resource(name="djNesListener")
    private IFXNewsListener newsListener;
    @Resource(name="djNesPersister")
    private IFXNewsPersister newsPersister;
}

@Resource和@Autowired标注的地方大致相同,都可以标注在属性域或方法上,也可以在构造方法或普通方法上标注。

  • @PostConstruct 和 @PreDestory

这两个注解并不是服务于依赖注入的,主要用于标注对象生命周期管理相关方法,与Spring的InitializingBean和DisposableBean接口,以及配置中的init-method和destroy-method起到类似作用。

只使用@Resource, @PostConstruct和@PreConstruct,并不能立马起作用。就像@Autowired需要AutowiredAnnotationBeanPostProcessor一样,这些注解也需要一个BeanPostProceesor,即CommonAnnotationBeanPostProcessor,这样这些注解才能发挥作用。

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

既然不管是@Autowired还是@Resource都需要添加相应的BeanPostProcessor到容器,那我们可以在基于XSD的配置文件中使用一个<context:annotation-config> 配置搞定义上所有的BeanPostProcessor。

<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:p="http://www.springframework.org/schema/p" 
  xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 
  <context:annotation-config/>
  <bean id="newsProvider" class="..FXNewsProvider"/>
  <!--其他bean定义-->
    ...
</beans>

  Spring提供的@Autowired加上@Qualifier和JSR250提供的@Resource等注解属于不同派系,如果要实现依赖注入的话,使用一个派别的注解就可以了。

  •  classpath-scanning

  不仅依赖关系可以用注解,不用xml配置,Bean的定义也可以不用配置。这就需要classpath-scanning功能了。

  使用相应的注解对组成应用程序的相关类进行标注后,classpath-scanning功能可以从某一顶层包(base package)开始扫描。当扫描到某个类标注了相应注解后,就会提取该类的相关信息,构建对应的BeanDefinition,然后把构建完的BeanDefinition注册到容器。

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        
xmlns:context
="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="org.spring21"/> </beans>

  如果要扫描的类定义在不同的包下面,也可以为base-package指定多个以逗号分隔的扫描路径。

  <context:component-scan>默认扫描的注解类型是@Component,不过在@Component语义基础上细化后的@Repository,@Servicce和@Controller也同样可以被扫描到。

  <context:component-scan>在扫描相关类定义并将它们添加到容器的时候,会使用一种默认的命名规则,来生成那些添加到容器的bean定义的名称(beanName)。这种命名规则就是类名称首字母小写后就是该类bean的beanName。如下例,如果使用默认名称就是如果想自定义一个名称,可以这样写:

@Component("djNewsListener") 
public class DowJonesNewsListener implements IFXNewsListener

  <context:component-scan>不仅把注册bean的功能完成了,甚至把<context:annotation-config>的任务也完成了,所以只用<context:component-scan>就可以扫描到bean, 并把它们的依赖关系也注册到了容器中。除此之外,<context:component-scan>的嵌套配置项可以对默认的扫描结果进行过滤以排除某些类。

<context:component-scan base-package="org.spring21">
  <context:include-filter type="annotation" 
   expression="cn.spring21.annotation.FXService"/>
  <context:exclude-filter type="aspectj" expression=".."/>
</context:component-scan>
原文地址:https://www.cnblogs.com/IvySue/p/6524632.html