Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
1. @Autowired 自动注入
1.1 注入规则
1)、默认优先 按照类型 去容器中找对应的组件:
applicationContext.getBean(BookDao.class);
找到就赋值
2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
applicationContext.getBean("bookDao")
3)、@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,
而不是使用属性名
4)、自动装配默认一定要将属性赋值好,没有就会报错;可以使用
@Autowired(required=false);
5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字
1.1.1 默认优先 按照类型 去容器中找对应的组(此时容器里面只有一个 【 BookDao】实例)
BookService 和 BookDao 因为 【@ComponentScan + @Service】被加入容器中 但是因为 BookService 里面包含 【BookDao 】,所以 BookService 里面加了 @Autowired直接拿到的就是 容器里面的 BookDao ,如果不加的话,BookService 里面的 BookDao = null
@Service
public class BookService {
//@Qualifier("bookDao")
//@Autowired(required=false)
//@Resource(name="bookDao2")
//@Inject
@Autowired
private BookDao bookDao;
}
- IOCTest_Autowired文件
- 发现 BookService 里面的【 BookDao】和容器里面的 【 BookDao】是同一个
1.1.2 多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
- @Repository注解的bean注入到容器中的名称是”bookDao “
- 另外又通过config文件 在容器中注入了另外一个 BookDao,名称是bookDao2
- 容器内有两个 bookDao,所以通过 applicationContext.getBean(BookDao.class)获取不到了,需要通过 名称来获取;
BookDao bean = (BookDao) applicationContext.getBean("bookDao2");
- 结果如下:
BookService里面还是 bookDao ,因为@Autowired 里面默认 自动导入 对应 BookDao的bookDao,
1.1.3 使用@Qualifier指定需要装配的组件的id,而不是使用组件的属性名
- 更改了之后,BookService里面变成了 bookDao2
1.1.4 自动装配默认一定要将属性赋值好,没有就会报错
- 当容器中没有 BookDao 的任何组件时,即没有扫描 BookDao这个类,或者没有手动注入BookDao 这个组件时,如果此时 【BookService】还要导入 @Autowired BookDao,会报错(因为BookService 初始化需要BookDao,但是容器中没有这个bean实例,所以会报错):
- 所以,@Autowired就需要设置(设置了之后表明这个属性不是必须的,默认可以为null)
@Autowired( required=false)
1.1.5 Spring进行自动装配的时候,默认使用首选的bean–@Primary
- 将 MainConifgOfAutowired 文件中 的 bookDao2 设置为首选
- BookService 里面
- 结果如下:BookService 里面导入的是bookDao2
2 @Resource(JSR250)和@Inject(JSR330)[java规范的注解]
- @Resource 按照 组件名称(byName) 进行装配,找不到与名称匹配的bean时才按照 类型(byType)进行装配
- @Autowired 是 按照 类型(byType)装配
@Resource:
可以和@Autowired一样实现自动装配功能;默认是按照 组件名称 进行装配的;
不能支持@Primary功能,不支持@Autowired(reqiured=false);
@Inject:
需要导入javax.inject的包,和Autowired的功能一样。
没有required=false的功能;
3 @Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值
- [标注在方法位置]:
@Bean+方法参数;参数从容器中获取
默认不写@Autowired效果是一样的;都能自动装配
//默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
@Component
public class Boss {
private Car car;
//构造器要用的组件,都是从容器中获取
public Boss(Car car){
this.car = car;
System.out.println("Boss...有参构造器");
}
public Car getCar() {
return car;
}
@Autowired
//标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值;
//方法使用的参数,自定义类型的值从ioc容器中获取
public void setCar(Car car) {
this.car = car;
}
}
- [标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的==@Autowired可以省略==参数位置的组件还是可以自动从容器中获取
//构造器要用的组件,都是从容器中获取
@Autowired
public Boss(Car car){
this.car = car;
System.out.println("Boss...有参构造器");
}
- [放在参数位置]:
public void setCar(@Autowired Car car) {
this.car = car;
}
4. AutowiredAnnotationBeanPostProcessor解析完成自动装配功能
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);
自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;
把Spring底层一些组件注入到自定义的Bean中;
xxxAware:功能使用xxxProcessor;
ApplicationContextAware==》ApplicationContextAwareProcessor;
实现了相关的ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware接口
@Component
public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("传入的ioc:"+applicationContext);
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
System.out.println("当前bean的名字:"+name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String resolveStringValue = resolver.resolveStringValue("你好 ${os.name} 我是 #{20*18}");
System.out.println("解析的字符串:"+resolveStringValue);
}
}