Spring内置了一些很有用的BeanPostProcessor接口实现类。比如有AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、EventListenerMethodProcessor等。这些Processor会处理各自的场景。
正是有了这些processor,把bean的构造过程中的一部分功能分配给了这些processor处理,减轻了BeanFactory的负担。
而且添加一些新的功能也很方便。比如Spring Scheduling模块,只需要添加个@EnableScheduling注解,然后加个@Scheduled注解修饰的方法即可,这个Processor内部会自行处理。
ApplicationContextAwareProcessor
ApplicationContextAwareProcessor实现BeanPostProcessor接口。
Spring容器的refresh方法内部调用prepareBeanFactory方法,prepareBeanFactory方法会添加ApplicationContextAwareProcessor到BeanFactory中。这个Processor的作用在于为实现*Aware接口的bean调用该Aware接口定义的方法,并传入对应的参数。比如实现EnvironmentAware接口的bean在该Processor内部会调用EnvironmentAware接口的setEnvironment方法,并把Spring容器内部的ConfigurableEnvironment传递进去。
具体的代码:
1 | // AbstractApplicationContext.class |
CommonAnnotationBeanPostProcessor
在AnnotationConfigUtils类的registerAnnotationConfigProcessors方法中被封装成RootBeanDefinition并注册到Spring容器中。registerAnnotationConfigProcessors方法在一些比如扫描类的场景下注册。比如 context:component-scan 标签或 context:annotation-config 标签的使用,或ClassPathBeanDefinitionScanner扫描器的使用、AnnotatedBeanDefinitionReader读取器的使用。
主要处理@Resource、@PostConstruct和@PreDestroy注解的实现。
在postProcessPropertyValues过程中,该processor会找出bean中被@Resource注解修饰的属性(Field)和方法(Method),找出以后注入到bean中。
1 | // CommonAnnotationBeanPostProcessor.class |
CommonAnnotationBeanPostProcessor的父类InitDestroyAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition过程会找出被@PostConstruct和@PreDestroy注解修饰的方法。
1 | // InitDestroyAnnotationBeanPostProcessor.class |
AutowiredAnnotationBeanPostProcessor
跟CommonAnnotationBeanPostProcessor一样,在AnnotationConfigUtils类的registerAnnotationConfigProcessors方法被注册到Spring容器中。
主要处理@Autowired、@Value、@Lookup和@Inject注解的实现,处理逻辑跟CommonAnnotationBeanPostProcessor类似。
1 | // AutowiredAnnotationBeanPostProcessor.class |
由于@Autowired注解可以在构造器中使用,所以AutowiredAnnotationBeanPostProcessor实现了determineCandidateConstructors方法:
1 |
|
RequiredAnnotationBeanPostProcessor
跟CommonAnnotationBeanPostProcessor一样,在AnnotationConfigUtils类的registerAnnotationConfigProcessors方法被注册到Spring容器中。
主要处理@Required注解的实现(@Required注解只能修饰方法),在postProcessPropertyValues过程中处理:
1 |
|
BeanValidationPostProcessor
默认不添加,需要手动添加。主要提供对JSR-303验证的支持,内部有个boolean类型的属性afterInitialization,默认是false。如果是false,在postProcessBeforeInitialization过程中对bean进行验证,否则在postProcessAfterInitialization过程对bean进行验证。
1 | // 手动注册BeanValidationPostProcessor |
定义一个使用JSR-303的bean:
1 |
|
最后实例化BeanForBeanValidation的时候,BeanValidationPostProcessor起作用,在postProcessBeforeInitialization过程中发现validate不通过,抛出异常:
Caused by: org.springframework.beans.factory.BeanInitializationException: Bean state is invalid: age - 最小不能小于10; id - 不能为null
AbstractAutoProxyCreator
这是一个抽象类,实现了SmartInstantiationAwareBeanPostProcessor接口。主要用于aop在Spring中的应用。
1 |
|
从这个postProcessBeforeInstantiation方法我们得出:如果使用了自定义的TargetSourceCreator,并且这个TargetSourceCreator得到了处理bean的TargetSource结果,那么直接基于这个bean和TargetSource结果构造出代理类。这个过程发生在postProcessBeforeInstantiation方法中,所以这个代理类直接代替了原本该生成的bean。如果没有使用自定义的TargetSourceCreator,那么走默认构造bean的流程。
1 |
|
从上面这些方法看出,要实例化的bean会通过wrapIfNecessary进行处理,wrapIfNecessary方法会根据情况是否wrap成代理类,最终返回这个结果。getEarlyBeanReference和postProcessAfterInitialization处理流程是一样的,唯一的区别是getEarlyBeanReference是针对单例的,而postProcessAfterInitialization方法是针对prototype的,针对prototype的话,每次实例化都会wrap成代理对象,而单例的话只需要wrap一次即可。
AbstractAutoProxyCreator抽象类有基于注解的子类AnnotationAwareAspectJAutoProxyCreator。这个AnnotationAwareAspectJAutoProxyCreator会扫描出Spring容器中带有@Aspect注解的bean,然后在getAdvicesAndAdvisorsForBean方法中会根据这个aspect查看是否被拦截,如果被拦截那么就wrap成代理类。
默认情况下,AbstractAutoProxyCreator相关的BeanPostProcessor是不会注册到Spring容器中的。比如在SpringBoot中加入aop-starter之后,会触发AopAutoConfiguration自动化配置,然后将AnnotationAwareAspectJAutoProxyCreator注册到Spring容器中。
MethodValidationPostProcessor
默认不添加,需要手动添加。支持方法级别的JSR-303规范。需要在类上加上@Validated注解,以及在方法的参数中加上验证注解,比如@Max,@Min,@NotEmpty …。 下面这个BeanForMethodValidation就加上了@Validated注解,并且在方法validate的参数里加上的JSR-303的验证注解。
1 |
|
MethodValidationPostProcessor内部使用aop完成对方法的调用。
1 | // MethodValidationPostProcessor.class |
ScheduledAnnotationBeanPostProcessor
默认不添加,使用@EnableScheduling注解后,会被注册到Spring容器中。主要使用Spring Scheduling功能对bean中使用了@Scheduled注解的方法进行调度处理。实现了BeanPostProcessor接口。
1 |
|
AsyncAnnotationBeanPostProcessor
默认不添加,使用@EnableAsync注解后,会被注册到Spring容器中。AsyncAnnotationBeanPostProcessor内部使用aop处理方法的调用。
1 | // AsyncAnnotationBeanPostProcessor.class |
ServletContextAwareProcessor
默认不添加,如果Spring容器是个Web容器,那么会被添加。比如GenericWebApplicationContext容器就在postProcessBeanFactory中添加了ServletContextAwareProcessor。postProcessBeanFactory方法是在Spring容器的refresh过程中被调用的。
ServletContextAwareProcessor实现了BeanPostProcessor接口,如果Spring容器中的bean实现了ServletContextAware或ServletConfigAware接口,那么会进行处理。
1 |
|
SpringBoot内部特有的BeanPostProcessor
EmbeddedServletContainerCustomizerBeanPostProcessor主要处理实现EmbeddedServletContainerCustomizer接口的bean。EmbeddedServletContainerCustomizer接口是SpringBoot提供的用于处理内置的Servlet容器的接口:
1 | public interface EmbeddedServletContainerCustomizer { |
这个EmbeddedServletContainerCustomizerBeanPostProcessor实现了BeanPostProcessor接口,处理过程:
1 |
|
SpringBoot内部EmbeddedServletContainerCustomizer接口的实现类有ServerProperties、ErrorMvcAutoConfiguration的内部类ErrorPageCustomizer等。 我们也可以实现自定义的EmbeddedServletContainerCustomizer用于修改内置Servlet容器的属性。
SpringBoot内部还有一些比如ConfigurationPropertiesBindingPostProcessor用于处于@ConfigurationProperties注解的processor、DataSourceInitializedPublisher用于发布DataSourceInitializedEvent事件等。读者可查看相关源码。