如果要想读懂Spring的源码,BeanPostProcessor和BeanFactoryPostProcessor这两种处理器机制应该要了解的。之前有过一篇文章,介绍了BeanPostProcessor后置处理器。
Spring中的后置处理器BeanPostProcessor
我们知道,Spring 提供了两种后处理Bean的扩展接口,分别为BeanPostProcessor和BeanFactoryPostProcessor,这两者在使用上是有区别的。
顾名思义:BeanPostProcessor是用于对Bean做后置增强处理的;BeanFactoryPostProcessor是用于对BeanFactory做增强处理的。下面就来学习一下,它们的具体区别。
二、BeanPostProcessorBeanPostProcessor:Bean级别的处理,针对某个具体的bean进行处理。
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName);
Object postProcessAfterInitialization(Object bean, String beanName);
}
BeanPostProcessor是个接口,上面是该接口仅有的两个方法,这两个方法执行的时机分别是Bean初始化前和Bean初始化后,具体这个初始化方法指的是什么方法呢?就是我们在定义Bean时,定义了 init-method 所指定的方法,如下所示:其中init()方法就是初始化方法。
这两个方法分别在init()方法前后执行,需要注意一点,如果我们定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。
既然是默认全部处理,那么我们怎么确认我们需要处理的某个具体的Bean呢?
我们可以看到提供的两个方法中,有两个参数。类型分别为Object 和 String,第一个参数是每个Bean的实例,第二个参数是每个Bean的name或者id属性的值。所以我们可以根据第二个参数,来确定我们将要处理的具体的Bean。
这个类型的后置处理器处理是发生在Spring容器的实例化和依赖注入之后。
三、BeanFactoryPostProcessorBeanFactoryPostProcessor:BeanFactory级别的处理,是针对整个Bean的工厂进行处理。
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}
BeanFactoryPostProcessor也是个接口,上面是该接口的描述,此接口只提供了一个方法,方法参数为ConfigurableListableBeanFactory(其实是个扩展后的一个容器),下面看看这个类里面定义了哪些方法
public interface ConfigurableListableBeanFactory
extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
void ignoreDependencyType(Class type);
void ignoreDependencyInterface(Class ifc);
void registerResolvableDependency(Class dependencyType, Object autowiredValue);
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
BeanDefinition getBeanDefinition(String beanName)
Iterator getBeanNamesIterator();
void clearMetadataCache();
void freezeConfiguration();
boolean isConfigurationFrozen();
void preInstantiateSingletons() throws BeansException;
}
其中有个方法名为getBeanDefinition的方法,我们可以根据此方法,找到我们定义Bean的BeanDefinition对象。然后我们可以对定义的属性进行修改,以下是BeanDefinition的定义。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(String parentName);
String getParentName();
void setBeanClassName(String beanClassName);
String getBeanClassName();
void setScope(String scope);
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(String... dependsOn);
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(String factoryBeanName);
String getFactoryBeanName();
void setFactoryMethodName(String factoryMethodName);
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
MutablePropertyValues getPropertyValues();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
何为BeanDefinition?
从这个BeanDefinition定义中,我们可以看到,上面的很多属性和方法都很熟悉,例如类名、scope、属性、构造函数参数列表、依赖的Bean、是否是单例类、是否是懒加载等。这里其实就是将Bean的定义信息存储到这个BeanDefinition相应的属性中,后面对Bean的操作就直接对BeanDefinition进行。setBeanClassName对应Bean标签中的class属性,所以当我们拿到BeanDefinition对象时,我们可以手动修改Bean标签中所定义的属性值。例如拿到这个BeanDefinition后,可以根据里面的类名、构造函数、构造函数参数,使用反射进行对象创建。
BeanDefinition是一个接口,是一个抽象的定义,实际使用的是其实现类,如 ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition等。
具体这个BeanDefinition是个什么对象,当我们在xml中定义了Bean标签时,Spring会把这些Bean标签解析成一个Javabean,这个BeanDefinition就是Bean标签对应的Javabean。
所以当我们调用BeanFactoryPostProcess方法时,这时候Bean还没有实例化,此时Bean刚被解析成BeanDefinition对象。(☆☆☆☆☆)
Spring容器初始化Bean大致过程:定义Bean标签---->将Bean标签解析成BeanDefinition ----> 调用构造方法实例化(IOC)(创建对象) ---->属性值依赖注入(DI)(属性赋值)
所以BeanFactoryPostProcessor中的BeanFactoryPostProcess方法的执行是发生在第二步之后,第三步之前。
而BeanPostProcessor作用于第三步之后。
四、小结以上两种都为Spring提供的后处理Bean的接口BeanPostProcessor和BeanFactoryPostProcessor,两者执行的时机不一样。前者在Bean实例化和属性赋值之后执行,后者是Bean实例化之前执行。从功能上来看,BeanFactoryPostProcessor对Bean的处理功能更加强大。因为它可以改变Bean的创建。