对于想了解Bean后置处理器-InstantiationAwareBeanPostProcessor#postProcessProperties的读者,本文将提供新的信息,我们将详细介绍bean后置处
对于想了解Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties的读者,本文将提供新的信息,我们将详细介绍bean后置处理器,并且为您提供关于@Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor、Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors、Bean后置处理器 - applyMergedBeanDefinitionPostProcessors、Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation的有价值信息。
本文目录一览:- Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties(bean后置处理器)
- @Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor
- Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
- Bean后置处理器 - applyMergedBeanDefinitionPostProcessors
- Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation
Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties(bean后置处理器)
代码片段:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//深度引用检查, 引用再引用
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//这里也是调用的实例化后的后置处理器, 只是调用的方法不一样
//这里会进行 @Autowired 和 @Resource 的注入工作
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
同样的, 通过调试的方式, 来确定这里使用了那些后置处理器:
1.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
2.CommonAnnotationBeanPostProcessor
3.AutowiredAnnotationBeanPostProcessor
ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
@Override
public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor''s
// postProcessProperties method attempts to autowire other configuration beans.
if (bean instanceof EnhancedConfiguration) {
((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
}
return pvs;
}
这里是对 EnhancedConfiguration 提供支持. 其实他继承了 BeanFactoryAware 接口, 并且什么都没干
public interface EnhancedConfiguration extends BeanFactoryAware {}
EnhancedConfiguration 是 ConfigurationClassEnhancer 的一个内部接口, 是给 spring 自己内部使用的, 开发人员用不了这个, 也没必要
CommonAnnotationBeanPostProcessor
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//找出类中标注了@Resource注解的属性和方法
//else if (field.isAnnotationPresent(Resource.class))
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
这里主要是对 @Resource 进行注入
findResourceMetadata在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition的时候执行过.
所以这里, 大概率是从缓存中拿取结果, 然后进行注入操作. 事实上, 也确实如此.
inject 最终会调用
org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject 方法
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
这里分两种情况进行处理, 一种是 通过字段注入, 另一种是通过方法注入.
字段注入的方式是比较多见的.
getResourceToInject() 方法是一个被重写了的方法:
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject
他是在一个内部类中被重写的方法.
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
默认情况下, lazy = false, 所以会走 getResource() 方法
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#getResource
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
if (StringUtils.hasLength(element.mappedName)) {
return this.jndiFactory.getBean(element.mappedName, element.lookupType);
}
if (this.alwaysUseJndiLookup) {
return this.jndiFactory.getBean(element.name, element.lookupType);
}
if (this.resourceFactory == null) {
throw new NoSuchBeanDefinitionException(element.lookupType,
"No resource factory configured - specify the ''resourceFactory'' property");
}
return autowireResource(this.resourceFactory, element, requestingBeanName);
}
根据设置的不同属性, 进不同的方法, 这里主要看 autowireResource , 因为一般情况是不需要去设置这些属性的
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
Object resource;
Set<String> autowiredBeanNames;
String name = element.name;
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
//优先使用 根据 name 注入, 这个 name 就是 beanName
//当 beanName 找不到时, 才就会去根据 type 来注入
//依据是 !factory.containsBean(name)
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
autowiredBeanNames = new LinkedHashSet<>();
//根据type(类型)来进行依赖注入
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {
//如果返回时 resource , 则表明, spring容器中找不到, 也创建不了 这个依赖的bean
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
}
}
else {
//根据name(名称)来进行依赖注入
resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
}
else {
resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
if (factory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
for (String autowiredBeanName : autowiredBeanNames) {
if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
}
}
}
return resource;
}
都说, @Resource 在不设置 name 和 type 的情况下, 是优先使用 name 去 获取/创建 依赖的 bean , 如果name找不到, 才会使用 type.
这段代码, 就是支撑的依据.
AutowiredAnnotationBeanPostProcessor
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
这里主要是对 @Autowired 和 @Value 进行注入的. findAutowiringMetadata
findAutowiringMetadata在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition的时候执行过.
所以此处, 是从缓存中拿取结果, 然后进行注入操作.
最终会调用本类中的方法:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
//根据 type 进行依赖注入
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
这里有一个隐藏的后置处理器: SmartInstantiationAwareBeanPostProcessor
留到下一篇看
@Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor
最近在遇到比较一个问题,通常我们在spring中使用@Configuration来注解一个类时,可以同时用Autowire 和@Value 给该配置类自动注入属性值,如下:
@Configuration
public class ConfigA {
@Autowired
private Environment environment;
@Value("${name}")
private string name;
@Bean
public A a() {
A a = new A();
a.name = name;
return a;
}
}
我们正常情况下都是能自动注入environment和name的,但是当在configration 中如果声明了一个BeanPostProcessor时,如下:
@Bean
public MyBeanPostProcessor myBeanPostProcessor(A a) {
log.info("env=:{}", environment);
MyBeanPostProcessor myBeanPostProcessor = new MyBeanPostProcessor();
myBeanPostProcessor.setA(a);
return myBeanPostProcessor;
}
你会发现打出来的log env 为null,同时A的name 也为null,这个配置类的 @Autowired和@Value都没有生效。
翻阅spring 的官网,其中有一段小tip,如下
Make sure that the dependencies you inject that way are of the simplest kind only. @Configuration classes are processed quite early during the initialization of the context, and forcing a dependency to be injected this way may lead to unexpected early initialization. Whenever possible, resort to parameter-based injection, as in the preceding example.
Also, be particularly careful with BeanPostProcessor and BeanFactoryPostProcessor definitions through @Bean. Those should usually be declared as static @Bean methods, not triggering the instantiation of their containing configuration class. Otherwise, @Autowired and @Value may not work on the configuration class itself, since it is possible to create it as a bean instance earlier than AutowiredAnnotationBeanPostProcessor.
意思就是BeanPostProcessor 和BeanFactoryPostProcessor 会在configuration 本身这个bean初始化之前,可以在spring onrefresh 方法中找到这段代码
踩坑记录一下。
Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
spring 在创建对象 (org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance) 的时候,使用了这个 构造函数后置处理器,用来选择使用哪个构造函数的.
所以这个后置处理器的执行时机是: 对象实例化之前执行
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
这里满足条件的后置处理器,就两个:
1.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
2. AutowiredAnnotationBeanPostProcessor
ImportAwareBeanPostProcessor
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
这个类并没有实现这个接口,而是父类去实现的:
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#determineCandidateConstructors
然而,他也是 啥也没干.
怎么感觉这个后置处理器,哪哪都有他,却哪哪都不干活.
AutowiredAnnotationBeanPostProcessor
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let''s check for lookup methods here...
if (!this.lookupMethodsChecked.contains(beanName)) {
try {
ReflectionUtils.doWithMethods(beanClass, method -> {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
Assert.state(this.beanFactory != null, "No BeanFactory available");
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition)
this.beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
}
}
});
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
}
this.lookupMethodsChecked.add(beanName);
}
// Quick check on the concurrent map first, with minimal locking.
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// Fully synchronized resolution now...
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
try {
//反射获取所有构造函数
rawCandidates = beanClass.getDeclaredConstructors();
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
//候选构造方法
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
Constructor<?> requiredConstructor = null;
Constructor<?> defaultConstructor = null;
//这个貌似是 Kotlin 上用的, 不用管它
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
//遍历这些构造函数
for (Constructor<?> candidate : rawCandidates) {
//判断构造方法是否是合成的
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
//查看是否有 @Autowired 注解
//如果有多个构造方法, 可以通过标注 @Autowired 的方式来指定使用哪个构造方法
AnnotationAttributes ann = findAutowiredAnnotation(candidate);
if (ann == null) {
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//有 @Autowired 的情况
if (ann != null) {
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with ''required'' Autowired annotation already: " +
requiredConstructor);
}
boolean required = determineRequiredStatus(ann);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with ''required'' Autowired annotation: " +
candidate);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
//无参构造函数的情况
else if (candidate.getParameterCount() == 0) {
//构造函数没有参数, 则设置为默认的构造函数
defaultConstructor = candidate;
}
}
//到这里, 已经循环完了所有的构造方法
//候选者不为空时
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null) {
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name ''" + beanName +
"'': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//类的构造方法只有1个, 且该构造方法有多个参数
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//这里不会进, 因为 primaryConstructor = null
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//这里也不会进, 因为 primaryConstructor = null
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
//如果方法进了这里, 就是没找到合适的构造方法
//1. 类定义了多个构造方法, 且没有 @Autowired , 则有可能会进这里
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//这里如果没找到, 则会返回 null, 而不会返回空数组
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
这个方法比较长,但是仔细看,是能看懂的。大致可以划分为几个步骤:
1. 获取类的所有构造方法
2. 遍历构造方法
|-> 只有一个无参构造方法,则返回 null
|-> 只有一个有参构造方法,则返回这个构造方法
|-> 有多个构造方法且没有 @Autowired, 此时 spring 则会蒙圈了,不知道使用哪一个了。这里的后置处理器,翻译过来,叫智能选择构造方法后置处理器.
当选择不了的时候,干脆返回 null
|-> 有多个构造方法,且在其中一个方法上标注了 @Autowired , 则会返回这个标注的构造方法
|-> 有多个构造方法,且在多个方法上标注了 @Autowired, 则 spring 会抛出异常,spring 会认为,你指定了几个给我,是不是你弄错了
注:
这地方有个问题需要注意一下,如果你写了多个构造方法,且没有写 无参构造方法,那么此处返回 null,
在回到 createBeanInstance 方法中,如果不能走 autowireConstructor (), 而走到 instantiateBean () 中去的话,会报错的.
因为类已经没有无参构造函数了
Bean后置处理器 - applyMergedBeanDefinitionPostProcessors
创建完对象之后, 接下来, 就应该想办法对属性进行注入了, 其中就包括 @Autowired 注入
但是在注入之前, 貌似 还没有对 @Autowired 进行扫描和解析.
代码块:
if (instanceWrapper == null) {
/**
* 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。
* createBeanInstance中包含三种创建 bean 实例的方式:
* 1. 通过工厂方法创建 bean 实例
* 2. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例
* 3. 通过无参构造方法方法创建 bean 实例
*
* 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB 增强 bean 实例。
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//调用属性合并后置处理器, 进行属性合并
//这里会进行 一些注解 的扫描
//CommonAnnotationBeanPostProcessor -> @PostConstruct @PreDestroy @Resource
//AutowiredAnnotationBeanPostProcessor -> @Autowired @Value
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
接着看里面的内容
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);
}
}
}
通过调试, 可以获取, 这里满足条件的, 有三个后置处理器, 按照调用先后顺序为:
1.CommonAnnotationBeanPostProcessor
2.AutowiredAnnotationBeanPostProcessor
3.ApplicationListenerDetector
接下来看看里面都干了啥
CommonAnnotationBeanPostProcessor
这一步, 主要是扫描作用.
1. 扫描 @PostConstruct 和 @PreDestroy (这个很直观的能看到, 其无参构造函数中, 出现了这两个注解)
2. 扫描 @Resource , 这个需要到 findResourceMetadata 中, 才能看到
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
/**
* 1.遍历扫描方法上标注了 @PostConstruct 和 @PreDestroy 注解的类
* 2.遍历扫描方法上标注了 @Resource 注解的类
* @param beanDefinition
* @param beanType
* @param beanName
*/
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
1. 调用父类方法, 进行@PostConstruct 和 @PreDestroy 扫描
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
findLifecycleMetadata最终会调用 org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#buildLifecycleMetadata 方法
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
//当前类解析完后, 拿到父类继续进行解析, 直到父类为 Object
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
这里就是遍历类和其父类, 进行查找的.
2. 进行 @Resource 扫描
Resource 扫描, 是在本类中完成的.
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#findResourceMetadata
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
这里主要看 buildResourceMetadata( ) 方法.
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//扫描字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
//静态字段上标注 @Resource , 会抛异常
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
//扫描方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
//如果目标方法, 没有参数, 或者有多个参数, 则抛出异常
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
//这里拿到方法名, 会去跟类中的属性进行匹配
//匹配的规则是: method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())
//这个 readMethod 就是 getXXX 或 isXXX, writeMethod 就是 setXXX
//如果匹配不上, pd = null
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
注意到, 这里只进行了扫描转换工作, 并没有进行属性注入工作.
AutowiredAnnotationBeanPostProcessor
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 ''javax.inject.Inject'' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
从这段代码, 可以猜测, 自动注入的类型, 是个集合, 这里有两个
1. @Autowired
2. @Value
findAutowiringMetadata() 最终会调用本类方法:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
//需要处理的目标类
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 通过反射获取该类所有的字段,并遍历每一个字段,通过方法 findAutowiredAnnotation 遍历每一个字段的所用注解,
// 如果用autowired修饰了,则返回 auotowired 相关属性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
// 校验autowired注解是否用在了static方法上
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//通过反射处理类的method
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
//这里也会进行属性的匹配, 按照规则 : method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())
//如果匹配不上, pd = null
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
//用@Autowired修饰的注解可能不止一个,因此都加在 elements 这个容器里面,一起处理
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
这里也只是进行了扫描, 没有进行属性注入工作.
ApplicationListenerDetector
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
this.singletonNames.put(beanName, beanDefinition.isSingleton());
}
这个类也是挺能凑热闹的. 这里没有进行任何扫描工作. 只是记录了容器中的 bean 是否是单例模式.
这里记录这个标志, 是为了后面用的. 对监听器进行过滤用的.
Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation
在 createBean 方法中, doCreateBean 方法前, 调用了这样一句代码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 在 bean实例化之前 应用后置处理,如果后置处理返回的bean不为空,则直接返回
// 返回的是一个寡妇对象, 属性什么的, spring不会去维护
// spring不推荐开发人员使用这个接口 InstantiationAwareBeanPostProcessor
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
这是一个扩展方法, 如果返回了 bean , 那么就不走后面的创建流程了.
要注意这里的执行时机: 对象实例化之前执行
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
InstantiationAwareBeanPostProcessor 这个后置处理器, 不但定义了 实例化之前的处理器, 还定义了 实例化之后的处理器.
所以, 这里如果返回的bean不为null, 还需要执行实例化之后的处理器, 来保证流程的完整性.
在这里, 就不看实例化之后的回调了.
直接看 applyBeanPostProcessorsBeforeInstantiation() 方法:
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
首先来看一下, 这个接口:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
注意到, 这个接口是 继承了 BeanPostProcessor , 表示他是一个 bean 的后置处理器. 和前面章节出现过的 BeanFactory 后置处理器 是不同的
通过断点调试, 不难发现, 6个后置处理器中, 满足条件的就三个, 按照执行顺序排列为:
1.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
2.CommonAnnotationBeanPostProcessor
3.AutowiredAnnotationBeanPostProcessor
那接下来, 就需要看一下, 里面分别干了什么
ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInstantiation
@Override
@Nullable
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
从这里看, 他本身都没有实现或重写这个方法, 而是由它的父类去实现的.
里面啥也没干, 直接返回了 null.
CommonAnnotationBeanPostProcessor
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
return null;
}
啥也没干
AutowiredAnnotationBeanPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInstantiation
@Override
@Nullable
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
他本身也没有实现这个方法, 而是父类去实现的.
里面也是啥也没干.
到这里, 这个后置处理器就执行完了, 大家都没干事情, 都是直接返回的 null. 所以, spring后续流程还是要走的
我们今天的关于Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties和bean后置处理器的分享已经告一段落,感谢您的关注,如果您想了解更多关于@Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor、Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors、Bean后置处理器 - applyMergedBeanDefinitionPostProcessors、Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation的相关信息,请在本站查询。
本文标签: