总结:
自动装配;
Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
1)、@Autowired:自动注入
1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
applicationContext.getBean("bookDaoooo"),
属性的名称指的就是
@Autowired
BookDao bookDaoooo; 中的bookDaoooo,
1)、意思是多个类型相同的组件时查找根据 指定的属性名bookDaoooo找的,
2)、而bookDaoooo对应的是相同类型组件中某个bean的id
3)、@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id【指的是bean的id】,而不是使用属性名
4)、自动装配默认一定要将属性赋值好,没有就会报错;
可以使用@Autowired(required=false);
5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字
BookService{
@Autowired
BookDao bookDao;
}
2)、Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
@Resource:
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能没有支持@Autowired(reqiured=false);
@Inject:
需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
@Autowired:Spring定义的; @Resource、@Inject都是java规范
***AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能;
1)@Resource@Inject是java的注解,按道理spring会优先支持java的注解,
2)当@Resource存在时@Autowired @Primary @Qualifier 包括@Inject 同时都会失效
3)@Resource 默认是按照bean id来装配的也就是beanName
3)、 @Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值
1)、[标注在方法位置]:@Bean标注的方法创建对象时,方法参数的值从容器中获取;默认不写@Autowired效果是一样的;都能自动装配
2)、[标在构造器上]:
1、默认加在容器中的组件,容器启动会调用无参构造器创建对象,在进行初始化赋值等操作
2、如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
3、构造器要用的组件都是从容器中获取
3)、放在参数位置:
//名字默认是类名首字母小写
@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 + "]";
}
}
@Configuration
@ComponentScan({"com.atguigu.service","com.atguigu.dao",
"com.atguigu.controller","com.atguigu.bean"})
public class MainConifgOfAutowired {
// @Primary
@Bean("bookDao2")
public BookDao bookDao(){
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
@Bean("bookDaoooo")
public BookDao bookDaoooo1(){
BookDao bookDao = new BookDao();
bookDao.setLable("3");
return bookDao;
}
}
@Service
public class BookService {
//@Qualifier("bookDao")
@Autowired(required=false)
//@Resource(name="bookDao2")
private BookDao bookDaoooo;
public void print(){
System.out.println(bookDaoooo);
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConifgOfAutowired.class);
BookService bookService = applicationContext.getBean(BookService.class);
System.out.println(bookService);
/**
* @Bean标注的方法创建对象的时候,方法参数的值从容器中获取
* @param car
* @return
*/
@Bean
public Color color(Car car){
Color color = new Color();
color.setCar(car);
return color;
}
以上例子:
BookDao 中的bean id是默认小时小写的类名 bookDao
随后又添加了 bean id 是bookDao2的 和 bookDaoooo的bean
他们都是类型相同 bean id不同
BookService 分别 添加@Autowired @Primary @Qualifier 注解
测试结果
- 1.添加@Autowired 注解,bookService中BookDao的Lable属性值是3:意味着@Autowired注解 通过属性名 bookDaoooo去容器中找到了 beanid 为bookDaoooo 的bean对象
- 2.为bookDao2 添加@Primary 注解后BookDao的Lable属性值是2:意味着有限选择了bookDao2 作为beanid去容器中获取bean对象
- 3.添加@Autowired 注解在添加@Primary注解再添加Qualifier注解时BookDao的Lable属性值是1:意味着Qualifier注解,是直接指定了beanid,通过bookDao 找到了beanid 为bookDao 的bean对象
结论:
这些注解同时存在时:默认容器优先选择 添加@Primary的bean,但当有Qualifier注解指定的bean时优先选择添加@Qualifier注解的bean - 4.优先级就是 @Qualifier>@Primary>@Autowired
5.@Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值
1)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配
2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
3)、放在参数位置: