spring自动注入的三种方式

摘要:
它可以与@Qualifier一起使用,以精确地指定要注入的bean的名称|-如果使用@Qualifieer,将通过将Qualifier的值与bean名称(即applicationContext getBean)匹配来找到它总之,当容器中有多个相同类型的组件时,加载优先级为:@Qualifier˃@Primary˃属性名。例如,以下容器包含三个BookDao组件@Configuration@ComponentScanpublicclassAutowiredBeanConfig{@BeanpublicBookDaobookDao1(){BookDaobookDao=newBookDao();bookDao.setLabel;returnbookDao;}@Bean@PrimarypublicBookDaobookDao2(){BookDaobookDao=newBookDao();bookDao.setLabel;returnbookDao;}@BeanpublicBookDaobookDao3(){BookDaobookDao=newBookDao();bookDao.setLabel;returnbookDao;}}自动注射模式如下:@Autowired@QualifierprivateBookDaobookDao3 ; 按照优先级顺序,@Qualifier˃@Primary˃属性名称,最后加载名为bookDao1的组件。例如,以下容器中有两个CarDao组件@Configuration@ComponentScanpublicclassResourceBeanConfig{@BeanpublicCarDaocarDao1(){CarDaocarDao=newCarDao();carDao.setLabel(“1”);returncarDao;}@BeanpublicCarDaocarDao(){CarDaocarDao=newCarDao(();carDao.setLabel(“2”);returncarDao;}}自动注射方法如下。CarDao2组件将根据属性名称注入。
所谓spring自动注入,是指容器中的一个组件中需要用到另一个组件(例如聚合关系)时,依靠spring容器创建对象,而不是手动创建,主要有三种方式:
1. @Autowired注解——由spring提供
2. @Resource注解——由JSR-250提供
3. @Inject注解——由JSR-330提供
 
@Autowired注解的使用方法
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

   /**
    * Declares whether the annotated dependency is required.
    * <p>Defaults to {@code true}.
    */
   boolean required() default true;

}
从源码可以看出:该注解可以用在构造器、方法、参数、属性上,最常见的是用在属性上。
该注解只有一个属性: required,默认为true,如果找不到匹配的bean则报错;设置为false,如果找不到匹配的bean则注入null,并不会报错。
可以配合@Qualifier使用,用于精准指定要注入的bean的名称。
可以配合@Primary使用,当容器中存在多个相同类型的组件时,用于指定优先加载哪一个,这个注解不能用在2个或更多同类型的组件上。
 
1. 当容器中只有一个该类型的组件时
|-不使用@Qualifier,会按bean类型查找,即applicationContext.getBean(bean.class),然后注入这个唯一的bean。
|-使用@Qualifier,会按Qualifier的value值跟bean名称匹配查找,即applicationContext.getBean("Qualifier的value值")。
2. 当容器中没有该类型的组件时
|-required=true——报错expected at least 1 bean which qualifies as autowire candidate。
|-required=false——注入null。
3. 当容器中存在多个该类型的组件时
|-不使用@Qualifier和@Primary时,会按属性名跟bean名称匹配查找,即applicationContext.getBean("属性名")。
|-使用@Primary、但不使用@Qualifier时,会优先加载带有@Primary注解的组件。
|-使用@Qualifier时,不管有没有使用@Primary,都会直接按Qualifier的value值跟bean名称匹配查找。
综上,当容器中存在多个同类型的组件时,加载优先级:@Qulifier>@Primary>属性名,例如下面这个容器中包含3个BookDao组件
@Configuration
@ComponentScan(basePackages = {"cn.monolog.service"})
public class AutowiredBeanConfig {

    @Bean(value = "bookDao1")
    public BookDao bookDao1() {
        BookDao bookDao = new BookDao();
        bookDao.setLabel("bookDao1");
        return bookDao;
    }

    @Bean(value = "bookDao2")
    @Primary
    public BookDao bookDao2() {
        BookDao bookDao = new BookDao();
        bookDao.setLabel("bookDao2");
        return bookDao;
    }

    @Bean(value = "bookDao3")
    public BookDao bookDao3() {
        BookDao bookDao = new BookDao();
        bookDao.setLabel("bookDao3");
        return bookDao;
    }
}
自动注入方式是这样的:
@Autowired
@Qualifier(value = "bookDao1")
private BookDao bookDao3;
按照优先级顺序,@Qulifier(bookDao1) > @Primary(bookDao2) > 属性名(bookDao3),最终加载的是名称为bookDao1的组件。
 

@Resource注解的使用方法
@Resource注解的使用跟@Autowired注解类似,但是需要注意:
1. 不支持@Primary注解,也不支持reuqired=false,即不允许注入null;
2. 该注解有一个属性name,类似于@Qualified精准匹配,优先级最高;
3. 默认按照属性名跟bean的名称匹配查找,如果不存在,再按类型匹配查找。
例如,下面这个容器中有两个CarDao组件
@Configuration
@ComponentScan(basePackages = {"cn.monolog.service"})
public class ResourceBeanConfig {

    @Bean(value = "carDao1")
    public CarDao carDao1() {
        CarDao carDao = new CarDao();
        carDao.setLabel("1");
        return  carDao;
    }

    @Bean(value = "carDao2")
    public CarDao carDao() {
        CarDao carDao = new CarDao();
        carDao.setLabel("2");
        return  carDao;
    }
}
自动注入方式如下,会按属性名注入carDao2组件。
//自动注入
@Resource
private CarDao carDao2;
但是改为下面这种注入方式:
//自动注入
@Resource(name = "carDao1")
private CarDao carDao2;
由于使用了name精准匹配,会忽略属性名,注入carDao1组件。
 

@Inject注解的使用方法
@Inject注解的使用方法跟@Autowired也基本相似,但是需要注意
1. 使用前需要导入jar包——javax.inject;
2. 支持@Primary注解,而且因为没有精确匹配,@Primary的优先级最高;
2. 不支持required=false,即不能注入null,如果找不到组件肯定报错;
3. 默认按照属性名跟bean的名称匹配查找,如果不存在,再按类型匹配查找。
 
例如,下面这容器中有一个EmployeeDao组件
@Configuration
public class InjectBeanConfig {
    @Bean(value = "employeeDao1")
    public EmployeeDao employeeDao1() {
        EmployeeDao employeeDao = new EmployeeDao();
        employeeDao.setLabel("1");
        return employeeDao;
    }
}
自动注入的方式如下
@Inject
private EmployeeDao employeeDao3;
spring会先按属性名查找名称为employeDao3的组件,即applicationContext.getBean("employeeDao3"),结果不存在;
然后按照类型查找,即applicationContext.getBean(EmployeDao.class),找到employeDao1组件,成功注入。
 
如果容器中有多个同类型组件,例如
@Configuration
public class InjectBeanConfig {
    @Bean(value = "employeeDao1")
    public EmployeeDao employeeDao1() {
        EmployeeDao employeeDao = new EmployeeDao();
        employeeDao.setLabel("1");
        return employeeDao;
    }
    @Bean(value = "employeeDao2")
    public EmployeeDao employeeDao2() {
        EmployeeDao employeeDao = new EmployeeDao();
        employeeDao.setLabel("2");
        return employeeDao;
    }
    @Bean(value = "employeeDao3")
    public EmployeeDao employeeDao3() {
        EmployeeDao employeeDao = new EmployeeDao();
        employeeDao.setLabel("3");
        return employeeDao;
    }
}
注入方式还是这样
@Inject
private EmployeeDao employeeDao3;
仍然会按属性名和bean的名称匹配,即applicationContext.getBean("employeeDao3"),找到employee3,成功注入。
 
但是如果其中某个组件加了@Primary注解,会忽略属性名,优先注入,例如
@Configuration
public class InjectBeanConfig {
@Bean(value
= "employeeDao1") public EmployeeDao employeeDao1() { EmployeeDao employeeDao = new EmployeeDao(); employeeDao.setLabel("1"); return employeeDao; }
@Bean(value
= "employeeDao2") @Primary
public EmployeeDao employeeDao2() { EmployeeDao employeeDao = new EmployeeDao(); employeeDao.setLabel("2"); return employeeDao; }
@Bean(value
= "employeeDao3") public EmployeeDao employeeDao3() { EmployeeDao employeeDao = new EmployeeDao(); employeeDao.setLabel("3"); return employeeDao; } }
无论注入时使用什么样的属性名,都会注入employeeDao2。

免责声明:文章转载自《spring自动注入的三种方式》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux 快捷键etopo1 arcmap 制图下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

spring的后置处理器——BeanPostProcessor以及spring的生命周期

后置处理器的调用时机 BeanPostProcessor是spring提供的接口,它有两个方法——postProcessBeforeInitialization、postProcessAfterInitialization。关于这两个方法的调用时机,可以参考spring源码注释。 /** * Apply this BeanPostProc...

Jsp基础知识

Jsp:Java Server Pages http://127.0.0.1:8080/weba/hello.html Tomcat执行过程: 浏览器通过http协议发送请求,以TCP协议作为底层,去tomcat的安装目录下找到webapps下的weba文件夹,再继续找到hello.html. http协议有协议头和协议头,底层是TCP,是无状态的,两次连...

logic:iterate 遍历

1. 遍历集合 <logic:iterate> 的 name 属性指定需要进行遍历的集合对象, 它每次从集合中检索出一个元素, 然后把它放在page 范围内, 并以id 属性指定的字符串来命名这个元素, 例如: <% Vector animals = new Vector(); animals.addElement("Dog"); ani...

Spring源码阅读-IoC容器解析

目录 Spring IoC容器 ApplicationContext设计解析 BeanFactory ListableBeanFactory HierarchicalBeanFactory MessageSource ApplicationEventPublisher EnvironmentCapable ResourceLoader和Resour...

VueBlog

1、数据库建表时: timestamp有两个属性,分别是CURRENT_TIMESTAMP 和ON UPDATE CURRENT_TIMESTAMP两种,使用情况分别如下: 1.CURRENT_TIMESTAMP  当要向数据库执行insert操作时,如果有个timestamp字段属性设为  CURRENT_TIMESTAMP,则无论这个字段有木有set值...

在Spring中配置Hibernate事务

     本文主要探讨怎么用Spring来装配组件及其事务管理。在J2EE工程里连接到一个简单的数据库并不是什么难题,但是如果要综合组装企业类的组件就变得复杂了。一个简单的组件有一个或多个数据库支撑,所以,我们说到整合两个或多个的组件时,我们希望能够维持跨组件的许多数据库的运作的原子性。   J2EE提供了这些组件的容器,可以保证处理的原子性和独立性。在没...