【Spring源码】- 05 扩展点之BeanPostProcessor

【Spring源码】- 05 扩展点之BeanPostProcessor

原创 张张 Reactor2020 昨天

原文链接:https://mp.weixin.qq.com/s?__biz=MzIxNjM0OTk3MQ==&mid=2247483769&idx=1&sn=7b0ad633d8e0741ecdacf4c498b32aca&chksm=978b2d05a0fca4132607289a51cdead9376a321f36cfb8f3aebebbcda156617585e8c61ca8f6&token=1573542807&lang=zh_CN#rd


类结构

BeanPostProcessor和BeanFactoryPostProcessor是Spring中两个最重要的扩展的。如果说BeanFactoryPostProcessor是面向IoC进行扩展,BeanPostProcessor就是面向Bean进行扩展。

从上面类结构图可以看出,BeanPostProcessor是一个顶层接口,下面有衍生出几个接口,实现对Bean创建、初始化等各个阶段进行更细化的扩展,所以BeanPostProcessor要比BeanFactoryPostProcessor复杂一些,可以实现更多扩展场景。

注册顺序

BeanPostProcessor被注册到IoC中才能起作用,在refresh()方法中registerBeanPostProcessors(beanFactory);这一语句完成BeanPostProcessor的注册工作,注册使用:addBeanPostProcessor(BeanPostProcessor beanPostProcessor)方法完成。

注册BeanPostProcessor也涉及到先后顺序关系,大致逻辑总结如下:

1、获取实现PriorityOrdered接口的BeanPostProcessor,然后通过getBean()方法实例化,排序后注册到容器中;

2、获取实现Ordered接口的BeanPostProcessor,然后通过getBean()方法实例化,排序后注册到容器中;

3、获取常规没有实现PriorityOrdered和Ordered接口BeanPostProcessor,然后通过getBean()方法实例化,注册到容器中;

4、上述步骤中MergedBeanDefinitionPostProcessor类型会单独存储到internalPostProcessors集合中,排序后保证放到末尾

5、最后移除ApplicationListenerDetector重新追加到最末尾

上面只是BeanPostProcessor注册先后顺序关系,并不会涉及到BeanPostProcessor的执行,由于BeanPostProcessor扩展出几个子类,下面我们来分析下每个子类的执行时机。

BeanPostProcessor

执行时机

接口定义见下:

publicinterfaceBeanPostProcessor{

@Nullable

defaultObjectpostProcessBeforeInitialization(Object bean, String beanName)throwsBeansException{

returnbean;

}

@Nullable

defaultObjectpostProcessAfterInitialization(Object bean, String beanName)throwsBeansException{

returnbean;

}

}

之前分析IoC容器启动流程时,介绍过initializeBean()方法完成Bean的init-method初始化工作,BeanPostProcessor就是在init-method执行前后进行扩展。

protectedObjectinitializeBean(finalString beanName,finalObject bean, @Nullable RootBeanDefinition mbd){

Object wrappedBean = bean;

if(mbd ==null|| !mbd.isSynthetic()) {

//触发BeanPostProcessor#postProcessBeforeInitialization()方法执行

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

}

//执行init-method方法

invokeInitMethods(beanName, wrappedBean, mbd);

if(mbd ==null|| !mbd.isSynthetic()) {

//触发BeanPostProcessor#postProcessAfterInitialization()方法执行

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}

returnwrappedBean;

}

再来看下这两个方法的调用逻辑:

publicObjectapplyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

throwsBeansException

{

Object result = existingBean;

for(BeanPostProcessor processor : getBeanPostProcessors()) {

Object current = processor.postProcessBeforeInitialization(result, beanName);

if(current ==null) {

returnresult;

}

result = current;

}

returnresult;

}

如果有postProcessBeforeInitialization()方法返回null,则表示该扩展点提前结束,不再需要继续执行后续BeanPostProcessor的postProcessBeforeInitialization方法。

再来看下postProcessAfterInitialization()方法执行逻辑是一样的:

@Override

publicObjectapplyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)

throwsBeansException

{

Object result = existingBean;

for(BeanPostProcessor processor : getBeanPostProcessors()) {

Object current = processor.postProcessAfterInitialization(result, beanName);

if(current ==null) {

returnresult;

}

result = current;

}

returnresult;

}

使用场景

invokeInitMethods(beanName, wrappedBean, mbd);方法执行Bean的init-method方法进行初始化,进入这个方法可以发现,这里只会执行实现InitializingBean和@Bean(initMethod="xxx")这两种方式设置的init-method方法,我们平时使用很多的@PostConstruct注解方式,其实是通过InitDestroyAnnotationBeanPostProcessor这个扩展类实现:

InitDestroyAnnotationBeanPostProcessor类实现了DestructionAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor这两个接口,间接方式继承BeanPostProcessor。InitDestroyAnnotationBeanPostProcessor就是在postProcessBeforeInitialization()方法中完成了对@PostConstruct注解方法的调用,所以其执行优先级比InitializingBean和@Bean(initMethod="xxx")这两种方式更加靠前。

如果你需要在init-method等Bean的初始化执行前后进行扩展,可以使用此接口实现。比如:判断Bean是否是线程池类,如果是则统一设置管理的线程名前缀:

publicObjectpostProcessBeforeInitialization(Object bean, String beanName)throwsBeansException{

if(beaninstanceofThreadPoolTaskExecutor) {

((ThreadPoolTaskExecutor) bean).setThreadNamePrefix("Post-");

}

returnbean;

}

还比如ApplicationListenerDetector在postProcessAfterInitialization()方法中实现将ApplicationListener类型的单例Bean注册到事件多播器上,实现对事件的监听:

publicObjectpostProcessAfterInitialization(Object bean, String beanName){

if(beaninstanceofApplicationListener) {

Boolean flag =this.singletonNames.get(beanName);

if(Boolean.TRUE.equals(flag)) {

// 如果当前 ApplicationListener bean scope 是 singleton 单例模式,则将它注册到应用的事件多播器上

this.applicationContext.addApplicationListener((ApplicationListener) bean);

}

elseif(Boolean.FALSE.equals(flag)) {

// 如果ApplicationListener bean scope 不是 singleton 单例模式,则尝试输出警告日志,说明情况,并移除

//所以ApplicationListener类型的只能是单例模式才会起作用

this.singletonNames.remove(beanName);

}

}

returnbean;

}

还比如ApplicationContextAwareProcessor这个就是在postProcessBeforeInitialization()方法中实现如ApplicationContextAware、EnvironmentAware等*Aware接口注入功能。实现原理非常简单,就是判断Bean是否实现接口,然后通过setter方式注入即可:

privatevoidinvokeAwareInterfaces(Object bean){

if(beaninstanceofEnvironmentAware) {

((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());

}

if(beaninstanceofEmbeddedValueResolverAware) {

((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);

}

if(beaninstanceofResourceLoaderAware) {

((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);

}

if(beaninstanceofApplicationEventPublisherAware) {

((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);

}

if(beaninstanceofMessageSourceAware) {

((MessageSourceAware) bean).setMessageSource(this.applicationContext);

}

if(beaninstanceofApplicationContextAware) {

((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);

}

}

InstantiationAwareBeanPostProcessor

前面分析BeanPostProcessor接口是在Bean的init-method方法执行前后进行扩展,其子接口InstantiationAwareBeanPostProcessor则可以在Bean的创建前后进行扩展,所以此扩展比BeanPostProcessor扩展更靠前。

接口定义见下:

publicinterfaceInstantiationAwareBeanPostProcessorextendsBeanPostProcessor{

//Bean创建之前回调该方法,beanClass就是将要被创建的Bean对应的Class信息

@Nullable

defaultObjectpostProcessBeforeInstantiation(Class<?> beanClass, String beanName)throwsBeansException{

returnnull;

}

//Bean创建之后回调该方法,参数bean就是创建完成的Bean对象

defaultbooleanpostProcessAfterInstantiation(Object bean, String beanName)throwsBeansException{

returntrue;

}

//postProcessProperties()方法在postProcessAfterInstantiation()方法之后紧挨着执行,其提供PropertyValues类型入参,所以在该方法中可以实现依赖操作

@Nullable

defaultPropertyValuespostProcessProperties(PropertyValues pvs, Object bean, String beanName)

throwsBeansException

{

returnnull;

}

//这个方法标注@Deprecated已经被废弃了,被postProcessProperties()方法取代了

@Deprecated

@Nullable

defaultPropertyValuespostProcessPropertyValues(

PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)

throwsBeansException{

returnpvs;

}

}

createBean()方法中Object bean = resolveBeforeInstantiation(beanName, mbdToUse);这条语句中会触发对postProcessBeforeInstantiation()方法的执行。

protectedObjectcreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

throwsBeanCreationException

{

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);//触发对postProcessBeforeInstantiation()方法的执行

if(bean !=null) {

returnbean;

}

...

Object beanInstance = doCreateBean(beanName, mbdToUse, args);//创建Bean实例(一般真正创建Bean的方法)

...

}

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法有个重要特性:如果该方法返回非null结果,则表示Bean提前创建完成,同时也会忽略掉后续的依赖注入、init-method初始化等步骤执行,最后只需要执行下BeanPostProcessor#postProcessAfterInitialization这个方法则整个Bean的创建流程就全部完成。

总结:在创建对象之前调用了postProcessBeforeInstantiation方法可以实现给扩展点一次创建代理的机会,如果代理对象返回不为空则不再继续常规方式创建Bean。

我们再来看下InstantiationAwareBeanPostProcessor接口中定义的另两个方法执行时机,Bean创建完成后会执行populateBean()进行依赖注入,它们就是在这个方法中进行触发回调,pupulateBean()方法大致见下:

protectedvoidpopulateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw){

//执行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法回调

if(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

for(BeanPostProcessor bp : getBeanPostProcessors()) {

if(bpinstanceofInstantiationAwareBeanPostProcessor) {

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {

return;

}

}

}

}

// 注解注入:后置处理器ibp#postProcessProperties,大名鼎鼎的@Autowired就是在这处理的。

PropertyDescriptor[] filteredPds =null;

if(hasInstAwareBpps) {

//执行InstantiationAwareBeanPostProcessor#postProcessProperties方法回调

for(BeanPostProcessor bp : getBeanPostProcessors()) {

if(bpinstanceofInstantiationAwareBeanPostProcessor) {

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

if(pvsToUse ==null) {

if(filteredPds ==null) {

//获取出对象的所有set get方法,现在是有一个 getClass()方法,因为继承了Object, 没什么其他卵用

filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);

}

//postProcessPropertyValues方法已废弃,被postProcessProperties替代

pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);

if(pvsToUse ==null) {

return;

}

}

pvs = pvsToUse;

}

}

}

if(pvs !=null) {

applyPropertyValues(beanName, mbd, bw, pvs);

}

}

上面代码翻译下大概就是:先执行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法回调,然后再去执行InstantiationAwareBeanPostProcessor#postProcessProperties,最后再去执行applyPropertyValues()完成PropertyValue方式的依赖注入。这里有个大名鼎鼎的@Autowired、@Value方式的依赖注入,就是借助于InstantiationAwareBeanPostProcessor#postProcessProperties()方法实现,这个实现类就是:AutowiredAnnotationBeanPostProcessor,简单看下依赖注入逻辑:

publicPropertyValuespostProcessProperties(PropertyValues pvs, Object bean, String beanName){

/**

* 从缓存中找到此类的@Autowired、@Value注解元数据,尝试注入

* InjectionMetadata,持有待注入的元数据信息,执行inject()方法,开始注入属性或方法参数。

*/

InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);

try{

//为beanName填充上属性bean

metadata.inject(bean, beanName, pvs);

}

catch(BeanCreationException ex) {

throwex;

}

catch(Throwable ex) {

thrownewBeanCreationException(beanName,"Injection of autowired dependencies failed", ex);

}

returnpvs;

}

这里有意义的代码就两行:

1、InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);获取Bean中需要依赖注入注入的元素,封装成一个InjectionMetadata对象,该对象有两个重要属性:

targetClass指定目标对象的Class;

Collection<InjectedElement> injectedElements:目标对象中每个需要依赖注入的元素都会封装成一个InjectedElement,然后存储到该集合中。根据@Autowired/@Value注解到字段上还是方法上,InjectedElement又可以分为两类:AutowiredFieldElement和AutowiredMethodElement。

2、metadata.inject(bean, beanName, pvs);:这个方法内部就是循环,对每个依赖元素InjectedElement调用inject()方法

if(!elementsToIterate.isEmpty()) {

for(InjectedElement element : elementsToIterate) {

if(logger.isTraceEnabled()) {

logger.trace("Processing injected element of bean '"+ beanName +"': "+ element);

}

element.inject(target, beanName, pvs);

}

}

比如我们一般将@Autowired标注到字段上,则这里会触发AutowiredFieldElement#inject()方法执行:

protectedvoidinject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)throwsThrowable{

Field field = (Field)this.member;//依赖注入字段

Object value;//存储需要注入的值

if(this.cached) {//如果已被缓存,则直接先从缓存中获取依赖注入值

value = resolvedCachedArgument(beanName,this.cachedFieldValue);

}

else{//还未被缓存过

//1.DependencyDescriptor:用于对该依赖注入描述信息

DependencyDescriptor desc =newDependencyDescriptor(field,this.required);

desc.setContainingClass(bean.getClass());

Set autowiredBeanNames =newLinkedHashSet<>(1);

Assert.state(beanFactory !=null,"No BeanFactory available");

TypeConverter typeConverter = beanFactory.getTypeConverter();

try{

/*

2.查找依赖注入的值

比如:

@Autowired

private TestService03 testService03;

这个value就是从IoC容器中查找到的TestService03对象

还比如:@Value("${spring.name}"),这个value就是从Spring上下文环境变量中解析出的spring.name变量值

*/

value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

}

catch(BeansException ex) {

thrownewUnsatisfiedDependencyException(null, beanName,newInjectionPoint(field), ex);

}

//3.下面synchronized块主要实现缓存功能,已被解析过的包装成ShortcutDependencyDescriptor类型,上面resolvedCachedArgument对这种类型会特殊处理

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 =newShortcutDependencyDescriptor(

desc, autowiredBeanName, field.getType());

}

}

}

else{

this.cachedFieldValue =null;

}

this.cached =true;

}

}

}

//4.查找到的依赖值不为null,则使用反射方式注入,因为是通过反射方式,所以@Autowired、@Value是不需要setter/getter方法也可以注入

if(value !=null) {

//通过反射方式将查找到的需要依赖注入的值设置到对象实例中

ReflectionUtils.makeAccessible(field);

field.set(bean, value);

}

}

SmartInstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor还有个子接口:SmartInstantiationAwareBeanPostProcessor,其定义如下:

publicinterfaceSmartInstantiationAwareBeanPostProcessorextendsInstantiationAwareBeanPostProcessor{

//推断类型

@Nullable

defaultClass predictBeanType(Class beanClass, String beanName)throwsBeansException {

returnnull;

}

//根据一定规则推断出Bean中优选的构造方法

@Nullable

defaultConstructor[] determineCandidateConstructors(Class beanClass, String beanName)

throwsBeansException {

returnnull;

}

defaultObjectgetEarlyBeanReference(Object bean, String beanName)throwsBeansException{

returnbean;

}

}

SmartInstantiationAwareBeanPostProcessor接口有三个方法,在实例创建前智能判断实例类型、智能判断构造函数、提起获取暴露Bean引用,该接口主要是spring框架内部使用,开发时很少去扩展该接口。

这里主要注意第三个方法:getEarlyBeanReference(),这个扩展方法主要与Spring中的循环依赖有关系。前面分析IoC容器启动时分析过:为了解决Spring中的循环依赖问题,在doCreateBean()方法内部,会将刚创建还未来得及进行依赖注入和初始化的半成品Bean提前暴露出去,addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));,注意这里不是直接将Bean暴露出去,而是通过() -> getEarlyBeanReference(beanName, mbd, bean)这句将Bean包装成ObjectFactory类型再暴露出去。

这里的一个核心就是:为什么不直接暴露Bean,而是将Bean包装成ObjectFactory再去暴露?将Bean包装成ObjectFactory再去暴露,调用getObject()方法时会触发SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference方法回调。

分析到这里,还不够完善,因为你可能会问:那这个方法回调又可以给我们解决什么问题呢?

可以利用Spring AOP原理来回答这个问题,Spring AOP主要基于AnnotationAwareAspectJAutoProxyCreator这个类实现,这个类实现了BeanPostProcessor接口,在postProcessAfterInitialization()方法中对创建完成的Bean采用动态代理方式将增强逻辑织入进去。

如果存在这样情况:A依赖B,B同时依赖A,这就是所说的Spring循环依赖,但是如果我们对A采用了AOP增强,这个过程会是怎样情况呢?

A对象创建完成后,由于可能会存在循环依赖问题,所以Spring会提前将A暴露出去;

然后对A进行依赖注入,发现A依赖B,然后A就卡主了,通过getBean(B)获取B实例时,这时就会进入B对象创建流程;

同样B对象创建完成后并将B对象提前暴露出去,然后开始执行B对象的依赖注入,通过getBean(A)方式获取,因为A已经提前暴露出去了,所以获取A是没问题的;

然后B顺利执行完依赖注入、init-method初始化工作,则B整个创建流程全部完成;

这时A中通过getBean(B)方法就可以返回B对象,然后依赖注入到A中,然后执行init-method初始化;

由于A是有AOP拦截的,在执行完init-method初始化方法后,postProcessAfterInitialization()执行时会给A通过动态代理方式织入增强逻辑;

这时,步骤3中给B注入的是A的原生对象,但是步骤6会给A创建一个代理对象,但是B中这时还是原生对象没法改变,这就会导致有的依赖注入的是原生对象,有的依赖注入的是代理对象,会出现错乱问题。如何解决呢?这个就是SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference这个扩展点作用。

A对象提前暴露时,利用ObjectFactory包装了一层,B对象在进行依赖注入时获取到对象A时,不是直接返回A,而是触发getEarlyBeanReference()方法执行,AnnotationAwareAspectJAutoProxyCreator类在getEarlyBeanReference()方法中实现判断A需要做动态代理,则对A进行动态代理后返回,这时B中依赖注入的就不是原生对象。

总结:SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference()方法是在循环依赖场景下,对提前暴露的Bean可以通过该扩展点进行处理。只有因为存在循环依赖,才会导致需要需要获取那些提前暴露的Bean时才会触发该扩展点,所以,理解这个扩展点关键在于你对Spring循环依赖的理解。

DestructionAwareBeanPostProcessor

DestructionAwareBeanPostProcessor是BeanPostProcessor子接口,其定义如下:

publicinterfaceDestructionAwareBeanPostProcessorextendsBeanPostProcessor{

//Bean销毁前回调方法

voidpostProcessBeforeDestruction(Object bean, String beanName)throwsBeansException;

//可以根据Bean进行过滤,哪些Bean需要用到当前这个回调

defaultbooleanrequiresDestruction(Object bean){

returntrue;

}

}

从名称就可以看出,该扩展主要用于Bean销毁之前,回调时机在:DisposableBeanAdapter#destroy()

publicvoiddestroy(){

//调用DestructionAwareBeanPostProcessor#postProcessBeforeDestruction,Bean销毁之前回调接口

if(!CollectionUtils.isEmpty(this.beanPostProcessors)) {

for(DestructionAwareBeanPostProcessor processor :this.beanPostProcessors) {

processor.postProcessBeforeDestruction(this.bean,this.beanName);

}

}

...

((DisposableBean)this.bean).destroy();//调用DisposableBean.destroy()

...

}

DestructionAwareBeanPostProcessor接口有个实现类InitDestroyAnnotationBeanPostProcessor,实现对@PreDestroy注解支持。该扩展接口本身是比较简单的,后续分析Bean生命周期destroy流程整体梳理。

MergedBeanDefinitionPostProcessor

MergedBeanDefinitionPostProcessor

publicinterfaceMergedBeanDefinitionPostProcessorextendsBeanPostProcessor{

voidpostProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

//Spring5.1新增接口,实现BeanDefinition重置通知,一般该方法实现重置前清理metadata等元数据缓存

defaultvoidresetBeanDefinition(String beanName){

}

}

我们主要看下postProcessMergedBeanDefinition()方法调用时机:

protectedObjectdoCreateBean(finalString beanName,finalRootBeanDefinition mbd,final@Nullable Object[] args)

throwsBeanCreationException

{

//1.创建对象

//2.执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition回调方法

synchronized(mbd.postProcessingLock) {

if(!mbd.postProcessed) {

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

mbd.postProcessed =true;

}

}

//3.提前暴露Bean

//4.populateBean(beanName, mbd, instanceWrapper);

//5.exposedObject = initializeBean(beanName, exposedObject, mbd);

}

MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition发生在Bean刚创建完成,Bean还未提前暴露之前。MergedBeanDefinitionPostProcessor在Spring中有很多的应用,比如:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、InitDestroyAnnotationBeanPostProcessor等。这个扩展的一般套路是和其它扩展点一起使用,其起到一个帮手角色,postProcessMergedBeanDefinition将需要处理的注解信息解析成元数据信息缓存起来,其它扩展点就可以从缓存中获取需要处理的注解信息进行处理。有关这扩展点更多的情况会在后续案例分析中再详细分析。

总结

BeanFactoryPostProcessor和BeanPostProcessor是Spring提供的两个最核心、最基础的扩展方式:一个面向IoC进行扩展,另一个面向Bean的创建流程进行各种扩展。BeanPostProcessor及其子类实现了对Bean创建过程中的各种扩展:Bean创建前后、Bean初始化前后、获取提前暴露对象前等等这些。Spring中大量注解简化了我们使用框架的复杂性,而这些注解很大一部分就是基于这些扩展进行处理,学习这些扩展点可以帮助我们更好的熟悉Spring的运行机理,同时可以在开发中帮助我们灵活的实现各种功能扩展。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容