Wednesday, October 6, 2010

Spring v3.0.2 Learning Note 8 - Annotation-based dependency injection

Annotation注解的注入方式

  • 准备工作
   1) 引入依赖包

将下列依赖包加入项目的classpath中:

%SPRING_DEP%\javax.annotation\com.springsource.javax.annotation\1.0.0\com.springsource.javax.annotation-1.0.0.jar

%SPRING_DEP%的路径参考http://wangxiangblog.blogspot.com/2010/10/spring-v302-learning-note-2-sample.html

           2)  在Java代码中使用@Autowire和@Resource注解的方式,需要context命名空间的支持
<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-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config />

</beans>

<context:annotation-config />这个配置隐式注册了多个对annotation进行解析的处理器,如
AutowireAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,
RequiredAnnotationBeanPostProcessor等。

  •  @Autowired & @Resource
在Java代码中使用@Autowired和@Resource注解的方式进行装配,二者的区别:
@Autowired 默认按照类型装配
@Resource  默认按照名称装配,当找不到与名称匹配的bean,再找类型匹配
 推荐采用@Resource注解的方式指定依赖对象,为J2EE的一部分,不是专属于Spring框架

使用方法:
@Autowired
private PersonDao personDao; // 用于字段上

@Autowired
public void setPersonDao (PersonDao personDao) {  // 用于属性的setter方法上
     this.personDao = personDao;
}

@Autowired注解是按类型装配依赖对象,默认情况下要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。 如果想使用按名称装配,可以结合@Qualifier注解一起使用,如:
@Autowired @Qualifier("personDao")
private PersonDao personDao;

@Resource注解和@Autowired注解一样,也可以标注在字段或者属性的setter方法上,它默认按照名称装配,名称也可以通过@Resource的name属性指定。
如果没有name属性,当标注在字段上时,默认取字段名作为bean名称寻找依赖对象;当标注在属性的setter方法上,默认取属性名作为bean名称寻找依赖对象

@Resource(name="personDao")
private PersonDao personDao; // 用于字段上

注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时,@Resource注解会按类型匹配。但一旦指定了name属性,就只能按照名称匹配了。

  • 验证
package com.spring.test.dao;

public class PersonDao {

    public void add() {
        System.out.println("This is add() method in DAO layer.");
    }
}
-------------------------------------------------------------------------------
package com.spring.test.manager.impl;

import javax.annotation.Resource;

import com.spring.test.dao.PersonDao;
import com.spring.test.manager.IPersonService;

public class PersonManager implements IPersonService {

    @Resource
    private PersonDao personDao; //应用在类的属性上
    private String name;

    public PersonManager() {
    }

    @Override
    public void save() {
        personDao.add();
        System.out.println("name is " + name);
    }

    public void setName(String name) {
        this.name = name;
    }

}

-------------------------------------------------------------------------
<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-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config />
    <bean id="personDao" class="com.spring.test.dao.PersonDao" />
    <bean id="personService" class="com.spring.test.manager.impl.PersonManager">
        <property name="name" value="CCC" />
    </bean>
</beans>

----------------------------------------------------------------------------
package com.spring.test.junit;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.test.manager.IPersonService;

public class PersonServiceTest {

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Test
    public void test() {
        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
                "spring.xml");
        IPersonService personService = (IPersonService) ctx
                .getBean("personService");
        personService.save();
    }

}
运行该测试用例,可在控制台看到如下结果:
This is add() method in DAO layer.
name is CCC
说明注入对象成功。

    @Resource
    private PersonDao personDao; 
spring会根据字段名personDao到配置文件中找到id/name为personDao的bean,如果可以找到,则注入到PersonManager中。如果我们修改配置这个bean ID为"personDaoXXX",
<bean id="personDaoXXX" class="com.spring.test.dao.PersonDao" />


再次运行测试用例,发现仍能得到正确结果,因为@Resource先按名称匹配,如果没有匹配到,就按照类型匹配,发现类型为com.spring.test.dao.PersonDao,就自动找到并注入。

当然也可以明确指定名称
@Resource(name="personDaoXXX")
    private PersonDao personDao;

运行测试用例,可能得到正确结果。


package com.spring.test.manager.impl;

import javax.annotation.Resource;

import com.spring.test.dao.PersonDao;
import com.spring.test.manager.IPersonService;

public class PersonManager implements IPersonService {

    private PersonDao personDao;
    private String name;

    public PersonManager() {
    }

    @Resource
    public void setPersonDao(PersonDao personDao) { //应用在属性的setter方法上也可以
        this.personDao = personDao;
    }

    @Override
    public void save() {
        personDao.add();
        System.out.println("name is " + name);
    }

    public void setName(String name) {
        this.name = name;
    }

}

No comments:

Post a Comment