Spring源码组件学习-BeanPostProcessor

定义

BeanPostProcessor称为Bean后置处理器,他是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前端)会回调BeanPostProcessor中定义的两个方法。

public interface BeanPostProcessor {
    Object interface postProcessBeforeInitialization(Object bean,String beanName) throws BeanException;

    Object interface postProcessAfterInitialization(Object bean,String beanName) throws BeanException;
}

其中postProcessBeforeInitiallization方法会在每一个bean对象的初始化方法调用之前回调;
其中postProcessAfterInitiallization方法会在每一个bean对象的初始化方法调用之后回调;

自定义BeanPostProcessor

查看BeanPostProcessor源码,可以看到它两个方法的参数都相同,其中第一个参数Object bean表示当前正在初始化的bean对象。此外两个方法都返回Object类型的实例,返回值既可以是将入参Object bean原封不动的返回出去,也可以对当前bean进行包装再返回。

执行原理

BeanPostProcessor的执行是定义在容器的刷新过程中,容器刷新对象具体的方法为:
AbstractApplicationContext.refresh()
refresh方法执行的调用栈中会去调用
AbstractAutowireCapableBeanFactory.deCreateBean()方法,该方法节选源码如下:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if(mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    invokeInitMethods(beanName, wrappedBean, mbd);

    if(mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialzation(wrappedBean, beanName);
    }
    return wrappedBean;
}

看到在调用初始化方法前后会分别调用applyBeanPostProcessorsBeforeInitializatioan()applyBeanPostProcessorsAfterInitialization()
applyBeanPostProcessorsBeforeInitialization()方法的源码如下

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    // 获取所有的BeanPostProcessor进行遍历
    for(BeanPostProcessor beanProcessor : getBeanPostProcessor()) {
        result = beanProcessor.postProcessBeanBeforeInitiallization(result, beanName);
        if(result == null) {
            return result;
        }
    }
    return result;
}

可以看到其逻辑为遍历得到容器中所有的BeanPostProcessor,然后一次执行postProcessBeforeInitialization,一旦返回null,就跳出for循环不执行后面的BeanPostProcessor.postProcessBeforeInitialization(),也就是说如果返回的
是null那么我们通过getBean方法将得不到目标Bean。
applyBeanPostProceorsAfterInitialzation()方法的逻辑与上面一样。

Spring中常见的几个Bean后置处理器

Spring底层的很多功能特性都是借助BeanPostProcessor的子类来实现。

AppliacationContextAwareProcessor

AppliacationContextAwareProcessor作用是当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象。

class ApplicationContextAwareProcessor implements BeanPostProcessor {
    private final ConfigurableApplicationCotext applicationContext;

    private final StringValueResolver embeddedVakueResolver;

    // Create a new ApplicationContextAwareProcessor for the given context
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext ) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }

    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
        // 这里bean是Car,它实现了ApplicationContextAware接口
        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                // 会执行这里回调实现类重写的setApplicationContext方法,然后将this.applicationContext注入给Car
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }

}

InitDestroyAnnotationBeanPostProcessor

InitDestroyAnnotationBeanPostProcessor后置处理器是用来处理自定义的初始化方法和销毁方法。Spring中提供了3种自定义初始化和销毁方法:

  1. 通过@Bean指定init-methoddestroy-method属性
  2. Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);
  3. @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
    @PreDestroy:在容器销毁bean之前通知我们进行清理工作

InitDestroyAnnotationBeanPostProcessor的作用就是让第3种方式生效。

InitDestroyAnnotationBeanPostProcessor会在Bean创建的时候通过反射的方式查找包含@PostConstruct和@PreDestroy注解的方法,然后再通过反射执行方法。InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()的源码

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 获取bean的metadata
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        // 执行@PostConstruct指定的init方法
        metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
}

ConfigurationClassPostProcessor

PostProcessorRegistrationDelegate

CommonAnnotationBean

RequiredAnnotationBeanPostProcessor

ApplicationListenerDetetor

Spring源码组件学习-BeanDefinitionParser

Spring自定义xml配置元素,读取xml配置加载bean的过程

xml扩展大概有以下几个步骤:

  1. 编写自定义类
  2. 编写xml schema来描述自定义元素
  3. 编写NamespaceHandler实现类编写
  4. 编写BeanDefinitionParser实现类
  5. 把以上组建注册到Spring

xml的schema约束:

schema约束定义了xml文档的结构、内容和语法,包括元素和属性、关系的结构以及数据类型等等。

  1. 所有的标签和属性都需要Schema来定义(schema本身w3c来定义)。
  2. 所有的schema文件都需要一个id,即namespace,其值为一个url,通常是这个xml的xsd文件地址。
  3. namespace值由targetNameSpace属性来指定。
  4. 引入一个schema约束,使用属性xmls,属性值即为对应schema文件的命名空间nameSpace
  5. 如果引入的schema非W3c组织定义的,必须指定schema文件的位置,schema文件的位置由schemaLocation来指定。
  6. 引入多个schema文件需要使用别名。别名形式如下:xmlns:alias。

对于上述配置文件的详细解读

NamespaceHandler

用于解析自定义命名空间下的所有元素。

Spring提供了默认实现类NamespaceHandlerSupport,只需要重写init()方法注册每个元素的解析器。

注册handlerschema(将组件串联起来)

为了让Spring在解析xml的时候能够感知到自定义的元素,需要将handlers格式和schemas格式的文件放入classPath下的META-INF/目录中。

  1. srping.handlers文件包含了xml schema url和handler类的映射关系,比如:

     http\://www.windforce.com/common/event=com.windforce.event.config.EvenrNamespaceHandler
    

    上面的冒号表示转义,key部分必须和xsd文件的中的targetNamespace值保持一致。

  2. spring.schemas文件包含xml schema url和xsd文件位置的映射关系。

     http\://www.windforce.com/common/event/event-1.0.xsd=com/windfore/common/event/config/event-1.0.xsd
    

BeanDefinitionParser

当解析xml配置文件时遇到在NamespaceHandler中指定的元素,Spring就会将元素交由相应的的BeanDefinitionParser来解析。

BeanDefinitionParser是一个接口,只有一个方法BeanDefinition parse(Element element, ParseContext parseContext),返回BeanDefinition

Spring源码组件学习-BeanDefinition

BeanDefinition

BeanDefinition的作用

bean的定义、包装是java bean的基础,在Spring中,BeanDefinition就是Bean的定义。
一个BeanDefinition描述了一个bean的实例,包括属性值、构造方法参数值和继承自它的类的更多信息。BeanDefinition仅仅是一个最简单的接口,主要功能是允许BeanFactoryPostProcessor例如PropertyPlaceHolderConfigure能够检索并修改属性值和别的bean的元数据。

一个BeanDefinition里拥有类名、scope、属性、构造函数参数列表、依赖的bean、是否是单例类、是否是懒加载等,其实就是将Bean的定义信息储存到这个BeanDefiniton相应中的属性中,后面对Bean的操作就直接对BeanDefinition进行,例如拿到这个BeanDefinition后,可以根据里面的类名、构造函数、构造函数参数、使用反射进行对象创建。

BeanDefinition的继承关系

父接口:
AttributeAccessor, BeanMetadataElement
子接口:
AnnotatedBeanDefinition
子类:
AbstractBeanDefinition, AnnotatedGenericBeanDefinition, ChildBeanDefinition, GenericBeanDefinition, RootBeanDefinition, ScannedGenericBeanDefinition

其中,AttaibuteAccessor接口定义了最基本的对任意对象的元数据的修改或者获取,主要方法有:

String[] attributeName();
Object getAttribute(String name)
boolean hasAttribute(String name)
Object removeAttribute(String name)
void setAttribute(String name, Object value)

BeanMetadataElement接口提供了一个getResource()方法,用来传输一个可配置的源对象。

BeanDefinition的抽象类AbstractBeanDefinition

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {

}

RootBeanDefinition

一个RootBeanDefinition定义表明它是一个可合并的bean definiton:即在Spring beanFactory运行期间,可以返回一个特定的bean。RootBeanDefinition可以作为一个重要的通用的bean definition视图。

##

BeanDefinitionProProcessor