概念理解:
自动装配:Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
一.可以利用@Autowired注解实现自动注入,这里省去了一些简单bean的创建,示例代码如下:
BookService.java
@Service public class BookService { @Autowired private BookDao bookdao; @Override public String toString() { return "BookService [bookdao=" + bookdao + "]"; } }
BookDao.java
@Repository public class BookDao { }
测试方法:
@Test public void test02() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigAutoware.class); BookService bookService = applicationContext.getBean(BookService.class) ; System.out.println(bookService);//打印出BookService中的BookDao对象 BookDao bookDao = applicationContext.getBean(BookDao.class); System.out.println(bookDao);//打印出容器中的BookDao对象
applicationContext.close(); //关闭容器
}
运行结果
BookService [bookdao=com.dao.BookDao@75f9eccc]
com.dao.BookDao@75f9eccc
从上面的运行结果可以看出:容器中的bean和自动注入到BookService中的bean是统一个BookDao@75f9eccc.@AutoWired注解的工作原理就是,如果某个类中引用容器中的bean,可以在该类的该属性上加@Autowired注解即可.
那么@AutoWired默认优先按照类型去容器中找对应的组件.
此种情况是容器中只有一个bean对象的时候,如果找到多个相同类型的组件,那么Spring将会抛出一个错误
expected single matching bean but found 2: bookDao,bookDao2
对于这种找到多个Bean对象的时候,可以使用@Qualifier("指定的id名字"),来指定具体使用哪个bean实例代码如下:
@Service public class BookService { @Qualifier("bookDao")//指定加载"bookDao" @Autowired private BookDao bookdao; @Override public String toString() { return "BookService [bookdao=" + bookdao + "]"; } }
此时,错误将会消失;容器中会加载bookDao对象;
另一种解决办法就是使用@Primary注解,该注解加载配置类的@Bean注解下,意为当存在两个相同类型的bean时,取被@Primary标注的bean对象
配置类代码如下:
@Configuration @ComponentScan({"com.wxj.service","com.wxj.dao"}) public class MainConfigAutoware { @Primary @Bean("bookDao2") public BookDao bookDao() { BookDao bookDao = new BookDao() ; bookDao.setLable("2"); return bookDao ; } }
更改BookDao类
@Repository public class BookDao { private String lable = "1"; public String getLable() { return lable; } public void setLable(String lable) { this.lable = lable; } @Override public String toString() { return "BookDao [lable=" + lable + "]"; } }
运行测试结果:
BookService [bookdao=BookDao [lable=2]]
容器中加载的是被@Primary标注的bean.
注意:如果@Qualifier和@Primary注解同时使用,首选@Qualifier指定的bean;
还有一种情况就是,容器中没有该类型的bean,运行测试类将会报错:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
根据Spring容器的提示可以看到,类中若使用@AutoWired注解实现自动装配,那么在容器中就至少有一个该类型的bean.那么若何解决该问题呢?可以通过指定@Autowired的required属性来说明该对象有就加载,没有就不加载
@Autowired(required=true):默认的情况,说明容器中必须存在被@Autowired注解的bean,
@Autowired(required=false):说明容器中有指定的bean就加载,没有就不加载.
扩展:@Autowired还可以加在其他位置;
1,方法上:Spring容器创建当前对象,就会调用方法完成赋值.方法使用的参数就是从ioc容器中进行获取
2,有参构造器:在容器创建bean对象时,也会从容器中进行选取.如果容器中只有一个有残构造器,注解还可以省略掉.
3,参数的位置:也是从容器中获取,@Bean标注的对象创建对象时方法的参数值也是从容器中获取.
二,@Resource(JSR250):可以和@Autowired一样实现自动装配.默认是按照组件的id进行装备,不支持@Primary和required属性.也不能和@Qualifier组合使用
三,@Inject(JSR330):需要导入javax.inject的包,和@Autowired一样的使用方法但是没有任何属性
扩展,以上注解的工作原理主要是依赖AutowiredAnnotationBeanPostProcessor类进行实现