一、属性赋值
- 属性赋值相关的注解
@Value
@PropertySource
springboot中的@ConfigurationProperties(prefix = "xxx")
二、自动装配
- 概念:Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值
1、@Autowired:自动注入
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的名字
2、@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
1、@Resource:可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;没有能支持@Primary功能。
2、@Inject:需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
总结:
- @Autowired:Spring定义的; @Resource、@Inject都是java规范
- AutowiredAnnotationBeanPostProcessor解析完成自动装配功能
三、自定义组件想要使用Spring容器底层的一些组件
- 例如:ApplicationContext,BeanFactory,xxx
1、Aware接口
- Aware是一个具有标识作用的超级接口,实现该接口的bean是具有被spring 容器通知的能力的,而被通知的方式就是通过回调。总之:直接或间接实现了这个接口的类,都具有被spring容器通知的能力。
-
继承接口:
- 可以知道这些xxxAware接口都只有一个setxxx方法,目的就是给实现该接口的类的xxx属性设置值。在spring中这些实现xxxAware接口的类是如何实现感应并设置xxx属性的值的呢,答案就是在spring容器中在工厂类创建实例后使用instanceof判断实例是否属于xxxAware接口的实例,如果结果是true的话,那么spring容器类就会调用实例的setXxx()方法给实例的xxx属性设置值。简单来说就是实现这些 Aware接口的Bean在被初始之后,可以从Spring容器中取得一些相对应的资源,例如实现BeanFactoryAware接口的Bean在初始后,Spring容器将会注入BeanFactory的实例,而实现ApplicationContextAware接口的Bean,在Bean被初始后,将会被注入 ApplicationContext的实例等等。
- 注意:
有六大类xxxAware是由spring容器自动注册在容器中的,应用程序不需要再次的在容器中注入了,但是如果我们实现其他的xxxAware,还必须在容器中注入才能使用,从ApplicationContextAwareProcessor源码可以解读出,这六类特殊的xxxAware是:
- @see org.springframework.context.EnvironmentAware
- @see org.springframework.context.EmbeddedValueResolverAware
- @see org.springframework.context.ResourceLoaderAware
- @see org.springframework.context.ApplicationEventPublisherAware
- @see org.springframework.context.MessageSourceAware
- @see org.springframework.context.ApplicationContextAware
2、从实现到原理再到实现
- 前面可知实现xxxAware接口主要是为了获取spring的一些特性
(1)自己实现一个接口获取spring的特性,比如BeanFactoryAware
public class Animal implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
- 注意:我们的Animal 类实现了aware接口,如果我们直接在应用中new一个Animal 的对象,当然是拿不到beanFactory变量的,我们必须在spring的配置文件中声明我们的fruit对象才行,也就是说Animal 对象必须交给容器进行管理,容器帮你把各种aware接口中想要注入的对象设置到bean中。具体看容器管理aware接口的代码实现,代码在AbstractAutowireCapableBeanFactory的initializeBean方法中:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 开始Bean初始化前处理、初始化、初始化后处理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
可以看出来,aware接口的各种处理是在属性设置完成之后、bean初始化之前完成的。显然的,如果我们直接new出来一个bean,这些框架性的特性是没有使用到的。但是上面提到的六中特殊的xxxAware,比如ApplicationContextAware,可以完成自动化在容器中进行接口注入,原来在应用中创建上下文容器时会注册一个BeanPostProcessor------ApplicationContextAwareProcessor,在这个类里面进行了context的注入,这样我们就能能够拿到bean中的context对象:
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
然后在AbstractApplicationContext.prepareBeanFactory方法中,进行对ApplicationContextAwareProcessor的注入。
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
3、自定义aware接口实现
- 知道原理后我们要实现自定义aware接口实现,需要完成下面两个步骤:
1.实现我们aware接口的postprocessor,并在容器中注册;
2.bean实体类集成我们自定义的aware接口并实现 - 具体案例实现:
(1)自定义aware接口:
public interface AppleAware {
void setApple(Apple a);
}
(2)自定义Processor实现BeanPostProcessor接口
public class AppleAwarePostProcessor implements BeanPostProcessor {
private Apple a;
public AppleAwarePostProcessor(Apple a) {
this.a = a;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof AppleAware) {
((AppleAware) bean).setApple(a);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
return bean;
}
}
(3)实现AppleAware 接口完成自定义bean注入
public class Market implements AppleAware {
private Apple a;
@Override
public void setApple(Apple a) {
this.a = a;
}
public String getName() {
return a.getName();
}
}
(4)测试
- 一定要把我们的BeanPostProcessor加入到当前容器中,这一点非常重要
public class TestAware {
public static void main(String args[]) {
ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
BeanPostProcessor bpp = new AppleAwarePostProcessor((Apple)beanFactory.getBean("apple"));
// 工厂对象中加入我们自定义的BeanPostProcessor
beanFactory.addBeanPostProcessor(bpp);
Market market = (Market) beanFactory.getBean("market");
System.out.println(market.getName());
}
}