https://www.cnblogs.com/leisurexi/p/13263542.html
https://segmentfault.com/a/1190000038251563
一、Spring依赖注入的方式
1.1、手动注入
1.1.1、使用XML的方式进行Setter方式的注入
public class SpringAction {
// 注入对象springDao
private SpringDao springDao;
// 一定要写被注入对象的set方法
public void setSpringDao(SpringDao springDao) {
this.springDao = springDao;
}
}
<!--配置bean,配置后该类由spring管理-->
1.1.2、构造器注入
这里的注入方式是在SpringAction的构造函数
中注入,也就是说在创建SpringAction
对象时要将SpringDao
和User
两个参数值传进来:
public class SpringAction {
//注入对象springDao
private SpringDao springDao;
private User user;
}
在XML文件中同样不用
<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
1.2、 自动注入
1.2.1、XML的自动注入
其实Spring也支持bean的自动注入。在定义bean时我们可以通过bean元素的autowire
属性来指定是否需要给当前bean来自动注入其所关联的bean。autowire属性的可选值有四个。
public class Hello {
public Hello(World world) {
}
}
<!-- 通过构造方法按照类型进行自动注入 -->
<bean id="hello" class="com.app.Hello" autowire="constructor"/>
1.2.2、@Autowired自动注入
三、AutowiredAnnotationBeanPostProcessor 类
AutowiredAnnotationBeanPostProcessor
是实现@Autowired
功能的主要类,它有一些方法是会用解析 @Autowired
注解并实现自动注入的功能。
3.1、 收集注入元信息
3.1.1、resolveBeforeInstantiation
- 首先在
CreateBean()
方法调用resolveBeforeInstantiation()
方法,执行InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
方法 如果
postProcessBeforeInstantiation
返回Bean
实例那么直接返回这个实例,如果返回nul 继续调用doCreateBean
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 有机会返回一个代理对象。SPring的扩展点
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// 执行创建Bean的过程
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
...
}
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// beforeInstantiationResolved表示该bean实例化前启用实例化后置处理器
// 1、Bean的属性中的beforeInstantiationResolved字段是否为true,默认是false。
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 2、是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true,程序设置
// 3、Bean的hasInstantiationAwareBeanPostProcessors属性为true,
// 这个属性在Spring准备刷新容器前转换BeanPostProcessors的时候会设置,
// 如果当前Bean实现了InstantiationAwareBeanPostProcessor则这个就会是true。
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 这里就是调用了BeanPost的前置方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 这里就是调用了BeanPost的后置方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 不满足2或者3的时候就会设置为false
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
hasInstantiationAwareBeanPostProcessors()
参考13-Spring源码refresh-registerBeanPostProcessors
中的代码块3
。通过hasInstantiationAwareBeanPostProcessors()
方法看有没有InstantiationAwareBeanPostProcessors
接口的实现类,如果有,就调用该接口的postProcessBeforeInstantiation
方法,如果这个接口有创建返回Bean,再调用BeanPostProcessor
接口的postProcessAfterInitialization
的方法,这样就完成了Bean的创建。
我们看到如果是在这一阶段通过InstantiationAwareBeanPostProcessor
接口产生了Bean
返回的话,那其就只会调用BeanPostProcessor
接口的postProcessAfterInitialization
方法,不会再调用其的例如一些Aware
等接口。
如果在上面没有通过InstantiationAwareBeanPostProcessor
产生Bean
的话,就会接着往下调用doCreateBean(beanName, mbdToUse, args)
方法。
通过断点调试, 不难发现, 6个后置处理器中, 满足条件的就三个, 按照执行顺序排列为:
- ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
- CommonAnnotationBeanPostProcessor
- AutowiredAnnotationBeanPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInstantiation
@Override
@Nullable
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
这里 **AutowiredAnnotationBeanPostProcessor **
的 **postProcessBeforeInstantiation()**
的方法会被调用,由于**AutowiredAnnotationBeanPostProcessor**
并没有重写这个方法,所以什么都不做。
3.1.2、findAutowiringMetadata 寻找注解元信息
操作 BeanDefinition
上面说过 postProcessBeforeInstantiation
方法返回 null
的话会继续执行doCreateBean
方法:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// ************重点代码********
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
...
populateBean(beanName, mbd, instanceWrapper);
...
在 doCreateBean
方法中,会调用调用applyMergedBeanDefinitionPostProcessors
方法:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
MergedBeanDefinitionPostProcessor
接口上面提到到的,AutowiredAnnotationBeanPostProcessor
实现了这个接口所以直接进入到AutowiredAnnotationBeanPostProcessor
中的 postProcessMergedBeanDefinition
方法:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 寻找需要注入的字段或方法,并封装成 InjectionMetadata
// 就是利用反射遍历类的所有字段和方法,找到标注了@Resource 注解的,并缓存
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
// 检查元数据中的注解信息
metadata.checkConfigMembers(beanDefinition);
}
InjectionMetadata 就是注入的元信息描述,主要字段如下
InjectedElement 就是注入的元素,主要字段如下:
查找注入元数据
接着继续进入到findAutowiringMetadata
,findAutowiringMetadata
会调用buildAutowiringMetadata
方法创建注入元数据,然后将元数据缓存到injectionMetadataCache
属性中:
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 首先从缓存中获取
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 判断是否需要刷新,即metadata为null或者metadata中存储的targetClass和当前clazz不等
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
// 这里相当于是一个double check,防止多线程出现的并发问题
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
...
// 构建注入元信息,见下文详解
metadata = buildAutowiringMetadata(clazz);
// 放入缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
创建需要注入的元信息AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 用于判断某个类是否可能 被标记指定的某个注解
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
// 用于判断某个类是否可能 被标记指定的某个注解
public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType) {
return isCandidateClass(clazz, annotationType.getName());
}
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
// 如果注解所在包是java开头,任何类上都可能标记这个注解
// Java开头的注解包就是JDK自带的注解,任何类都可能标记.这个时候返回True就没什么问题
if (annotationName.startsWith("java.")) {
return true;
}
// 注解所在包不是java开头的情况
// 可以认为是自定义注解,例如Spring的@Service @Autowired @Value 对Spring来说就是其自定义注解
// 如果类的包是以java开头,则不可能标记自定义的注解
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}
// 这里的class就是自己的class类。如果类的包是以java开头,则不可能标记自定义的注解
// 如果类的包不是以java开头
static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
return (type.getName().startsWith("java.") || type == Ordered.class);
}