Spring2.5基于Annotation装配Bean

      Spring注解是从2.5版本开始提供的,基于注解的依赖注入功能延续了Spring框架内在IoC容器设计与实现上的一致性。除了依赖关系的“表达”方式上的不同,底层的实现机制基本保持一致。

      Spring2.5提供的基于注解的依赖注入方式主要有@Autowired和@Qualifier;下面看看看看他们是如何使用的以及如何实现的?

  • @Autowired:byType
package com.mengma.ioc;
public interface PersonService {
    public void addPerson();
}
  1. 构造方法上
package com.mengma.ioc;
public class PersonServiceImpl implements PersonService {
    // 定义接口声明
    private PersonDao personDao;
    // 提供有参构造器,用于依赖注入
    @Autowired
    public PersonServiceImpl(PersonDao personDao) {
        this.personDao = personDao;
    }
    // 实现PersonService接口的方法
    @Override
    public void addPerson() {
        personDao.add(); // 调用PersonDao中的add()方法
        System.out.println("addPerson()执行了...");
    }
}

    2.属性上

package com.mengma.ioc;
public class PersonServiceImpl implements PersonService{
    // 定义接口声明
    @Autowired
    private PersonDao personDao;
    // 实现PersonService接口的方法
    public void addPerson() {
        personDao.add(); // 调用PersonDao中的add()方法
        System.out.println("addPerson()执行了...");
    }
}

 3.setter或其他方法上

package com.mengma.ioc;
public class PersonServiceImpl implements PersonService{
    // 定义接口声明
    private PersonDao personDao;
    // 实现PersonService接口的方法
    @Autowired
    public void addPerson() {
        personDao.add(); // 调用PersonDao中的add()方法
        System.out.println("addPerson()执行了...");
    }
}

现在,我们在上面3个地方都可以标注@Autowired,希望被@Autowired标注的依赖能被注入,但是,仅将@Autowired标注于类定义中并不能让Spring的IoC容器自己去找这些注解,然后注入符合条件的依赖对象。容器需要某种方式去了解,哪些对象标注了@Autowired,哪些对应可以作为可选的依赖对象来注入给需要的对象。在考虑使用什么方式实现这一功能之前,我们先比较一下原有的自动绑定功能与使用@Autowired之后产生了哪些差异。

      使用自动绑定时,我们需要配置所有相关的bean到容器的配置文件中,然后使用default-autowire或者autowire告知容器,依照这两种属性指定的绑定方式,将容器中各个对象绑定到一起,如下面的配置信息:

<beans default-autowire="byType">
    <bean id="personService" class="com.mengma.ioc.PersonServiceImpl" autowird="byType"/>
    <bean id="personDao" class="" />
</beans>

在使用@Autowired之后,default-autowire或者autowire的职责就转给了@Autowired,所以,容器的配置就只剩下孤零零的bean定义,如下所以:

<beans>
    <bean id="personService" class="com.mengma.ioc.PersonServiceImpl" />
    <bean id="personDao" class="" />
</beans>

为了给容器中定义的每个bean定义对应的实例注入依赖,可以遍历他们,然后通过反射,检查每个bean定义对应的类上各种可能位置上的@Autowired,如果存在的话,就可以从当前容器管理的对象中获取符合条件的对象,设置给@Autowired所标注的属性域、构造方法或者方法定义。如果按照这个实现逻辑,我们是否可以提供一个Spring的IoC容器使用的BeanPostProcessor自定义实现,让这个BeanPostProcessor在实例化bean定义的过程中,来检查当前对象是否有@Autowired标注的依赖。Spring类AutowiredAnnotationBeanPostProcessor已经实现了它。那么最终的配置如下:

<beans>
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
    <bean id="personService" class="com.mengma.ioc.PersonServiceImpl" />
    <bean id="personDao" class="" />
</beans>
  • @Qualifier : byName

与 @Autowired 注解配合使用,当@Autowired标注的依赖在容器中找到多个实例与之对应时,需要通过@Qualifier去byName自动绑定 .

      Spring自身除了注解外,Java 从JDK 5.0 以后,提供了@Resource和@PostConstruct以及@PreDestroy的 Annotation(注解)功能,Spring 也提供了对 Annotation 技术的全面支持。

  • @Resource:byName

@Resource和@Autowired一样都可以标注在属性,构造方法和普通方法上,同样的,就像@Autowired需要AutowiredAnnotationBeanPostProcessor为它与IoC容器牵线搭桥一样,JDK5.0的这些注解也同样需要一个BeanPostProcessor帮助他们实现自身的价值。这个BeanPostProcessor就是org.springframework.context.annotation.CommonAnnotationBeanPostProcessor,只有将CommonAnnotationBeanPostProcessor添加到容器,注解才能发挥作用,通常如下配置:

<beans>
    <bean class="org.springframework.beans.factory.annotation.CommonAnnotationBeanPostProcessor"/>
    <bean id="personService" class="com.mengma.ioc.PersonServiceImpl" />
    <bean id="personDao" class="" />
</beans>

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

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	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/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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="personService" class="com.mengma.ioc.PersonServiceImpl" />
    <bean id="personDao" class="" />

</beans>

<context:annotion-config>不到帮我们把AutoWiredAnnotionBeanPostProcessor和CommonAnnotationBeanPostProcessor注册到容器,同事还会把PersistenceAnnotationBeanPostProcessor和RequiredAnnotationBeanPostProcessor一并进行注册。 

到这里,我们是不是觉得,这是什么注解呀,一半分散在Java源代码中(@Autowired标注的信息),一半依然留在XML配置文件中,能否有一种更彻底的方法吗?答案是肯定的,它就是classpath-scanning,使用相应的注解对组成应用程序的相关类进行标注后,classpath-scanning功能可以从某一顶层包开始扫描,当扫描到某个类标注了相应的注解之后,就会提取该类的相关信息,构建对应的BeanDefinition,然后把构建完的BeanDefinition注册到容器。

classpath-scanning功能的触发是由<context:component-scan>决定的。添加XML配置文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	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/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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=“com.mengma”/>

</beans>

现在<context:component-scan>将遍历扫描com.mengma路径下的所有类型定义,寻找标注了相应注解的类,并添加到IoC容器。 <context:component-scan>默认扫描的注解类型是@Component。不过,在@Component语义基础上细化后的@Contoller、@Service和@Repository也同样能获得,而且<context:component-scan>,同时会将AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor一并注册到容器中,所以,@Autowired和@Resource也能满足依赖注入。

  • @Component

可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。

  • @Controller

通常作用在控制层(如 Struts2 的 Action),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

  • @Service

通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

  • @Repository

用于将数据访问层(DAO层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

后面会继续补充后面版本的注解

发布了169 篇原创文章 · 获赞 6 · 访问量 3472

猜你喜欢

转载自blog.csdn.net/weixin_42073629/article/details/105171653
今日推荐