深圳住房建设部官方网站,北京做兼职网站,乐清新闻,建立自己的购物网站文章目录一、BeanPostProcessor的作用1. 源码2. 使用案例二、Spring生命周期中的BeanPostProcessor三、BeanPostProcessor对PostConstruct的支持四、BeanPostProcessor中的顺序性五、总结一、BeanPostProcessor的作用 BeanPostProcessor提供了初始化前后回调的方法#xff0c;…
文章目录一、BeanPostProcessor的作用1. 源码2. 使用案例二、Spring生命周期中的BeanPostProcessor三、BeanPostProcessor对PostConstruct的支持四、BeanPostProcessor中的顺序性五、总结一、BeanPostProcessor的作用 BeanPostProcessor提供了初始化前后回调的方法Spring中常见的扩展就是在初始化前后对Bean进行的扩展。BeanDefinition注册完成之后在创建Bean过程中的初始化前后分别调用其中定义的方法。 其操作对象为已经实例化且进行了属性填充待初始化的Bean实例。 1. 源码
public interface BeanPostProcessor {/*** 初始化前调用*/Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/*** 初始化后调用*/Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}注意方法的返回值为原始实例或者包装后的实例。如果返回null会导致后续的BeanPostProcessor不生效BeanPostProcessor是可以注册多个的。 2. 使用案例 public class BeanPostProcessorDemo {public static void main(String[] args) {// 创建基础容器// BeanFactory作为基础容器,可以手动将BeanPostProcessor注册到容器中去的。// 同时也可以采用扫描或者定义的方式注册到容器中。DefaultListableBeanFactory beanFactory new DefaultListableBeanFactory();// 加载xml配置文件XmlBeanDefinitionReader reader new XmlBeanDefinitionReader(beanFactory);reader.loadBeanDefinitions(spring-bean-post-processor.xml);// 添加BeanPostProcessorbeanFactory.addBeanPostProcessor(new UserBeanPostProcessor());User user beanFactory.getBean(User.class);System.out.println(user);}
}
Data
class User{private String userName;private Integer age;private String beforeMessage;private String afterMessage;public void initMethod(){System.out.println(初始化:this);this.setUserName(小明);this.setAge(18);}
}
class UserBeanPostProcessor implements BeanPostProcessor{Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof User){System.out.println(初始化前:bean);((User) bean).setBeforeMessage(初始化前信息);}return bean;}Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof User){System.out.println(初始化后:bean);((User) bean).setAfterMessage(初始化后信息);}return bean;}
}初始化前:User(userNamenull, agenull, beforeMessagenull, afterMessagenull)
初始化:User(userNamenull, agenull, beforeMessage初始化前信息, afterMessagenull)
初始化后:User(userName小明, age18, beforeMessage初始化前信息, afterMessagenull)
User(userName小明, age18, beforeMessage初始化前信息, afterMessage初始化后信息)打印结果分析 初始化前User(userNamenull, agenull, beforeMessagenull, afterMessagenull) 该结果是postProcessBeforeInitialization方法中输出的内容这个时候User实例还只是进行了实例化还未进行到初始化步骤所以所有的属性都为null说明该方法确实是初始化执行的。——此时的初始化指的是bean对象的init方法初始化User(userNamenull, agenull, beforeMessage初始化前信息, afterMessagenull) 该结果为自定义的初始化方法initMethod方法中输出的内容这个时候User实例真正初始化而beforeMessage中的值正是在postProcessBeforeInitialization设置的。初始化后User(userName小明, age18, beforeMessage初始化前信息, afterMessagenull) 该结果是postProcessAfterInitialization中输出内容从打印结果可以看出它的确是在自定义initMethod后。 二、Spring生命周期中的BeanPostProcessor Spring中Bean总体上来说可以分为四个周期实例化、属性赋值、初始化、销毁。 而BeanPostProcessor则是在初始化阶段的前后执行。 首先看AbstractAutowireCapableBeanFactory源码中doCreateBean方法该方法实际就是创建指定Bean的方法。 其中有三个重要的方法createBeanInstance、populateBean、initializeBean。 这三个方法分别代表了Spring Bean中的实例化、属性赋值和初始化三个生命周期。 BeanPostProcessor是在初始化前后调用所以查看initializeBean中的方法详情即可。 protected Object initializeBean(String beanName, Object bean, Nullable RootBeanDefinition mbd) {// 处理BeanNameAware、BeanClassLoaderAware、BeanFactoryAwareif (System.getSecurityManager() ! null) {AccessController.doPrivileged((PrivilegedActionObject) () - {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}// 处理BeanPostProcessorObject wrappedBean bean;if (mbd null || !mbd.isSynthetic()) {// 回调postProcessBeforeInitialization方法wrappedBean applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {// 处理InitializingBean和BeanDefinition中指定的initMethodinvokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd ! null ? mbd.getResourceDescription() : null),beanName, Invocation of init method failed, ex);}if (mbd null || !mbd.isSynthetic()) {//回调postProcessAfterInitialization方法wrappedBean applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}从上面的源码可以看出首先是处理部分Aware相关接口然后接着就是处理BeanPostProcessor中的postProcessBeforeInitialization方法该方法详情如下 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {Object result existingBean;// 依次处理BeanPostProcessorfor (BeanPostProcessor processor : getBeanPostProcessors()) {Object current processor.postProcessBeforeInitialization(result, beanName);// 如果放回null,则直接返回。后续BeanPostProcessor中的postProcessBeforeInitialization不再执行if (current null) {return result;}result current;}return result;
}该方法就是执行postProcessBeforeInitialization回调的详情内容从该实现可以知道BeanPostProcessor可以有多个而且会按照顺序依次处理。如果只要其中的任意一个返回null则后续的BeanPostProcessor的postProcessBeforeInitialization将不会再处理了。 接着就是执行初始化方法即invokeInitMethods方法被调用。 protected void invokeInitMethods(String beanName, Object bean, Nullable RootBeanDefinition mbd) throws Throwable {boolean isInitializingBean (bean instanceof InitializingBean);if (isInitializingBean (mbd null || !mbd.isExternallyManagedInitMethod(afterPropertiesSet))) {if (logger.isTraceEnabled()) {logger.trace(Invoking afterPropertiesSet() on bean with name beanName );}// 如果当前Bean实现了InitializingBean接口则会执行它的afterPropertiesSet()方法if (System.getSecurityManager() ! null) {try {AccessController.doPrivileged((PrivilegedExceptionActionObject) () - {((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {((InitializingBean) bean).afterPropertiesSet();}}// 如果在BeanDefinition中定义了initMethod则执行初始化方法if (mbd ! null bean.getClass() ! NullBean.class) {String initMethodName mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) !(isInitializingBean afterPropertiesSet.equals(initMethodName)) !mbd.isExternallyManagedInitMethod(initMethodName)) {invokeCustomInitMethod(beanName, bean, mbd);}}
}从上面代码也进一步验证了BeanPostProcessor中的postProcessBeforeInitialization方法的确是在初始化前调用。 当invokeInitMethods执行之后接着就执行applyBeanPostProcessorsAfterInitialization方法。 Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current processor.postProcessAfterInitialization(result, beanName);if (current null) {return result;}result current;}return result;
}该方法与applyBeanPostProcessorsBeforeInitialization几乎就是相同的不同的在于它执行的是postProcessAfterInitialization。至此Spring Bean的初始化也就完成了。 三、BeanPostProcessor对PostConstruct的支持 通过上面了解了Spring Bean生命周期中初始化的过程但实际上Spring对于JSR250也支持例如对PostConstruct注解的支持。 在Spring中有一个CommonAnnotationBeanPostProcessor类这个类的注释中有说到这个类就是用来对JSR250及其他一些规范的支持。 从上图中我们可以看出CommonAnnotationBeanPostProcessor并没有直接对BeanPostProcessor有所实现它继承InitDestroyAnnotationBeanPostProcessor该类而对PostConstruct的实现主要在该类中。 而对BeanPostProcessor的实现代码如下 Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 1.生命周期元数据封装LifecycleMetadata metadata findLifecycleMetadata(bean.getClass());try {// 2.执行InitMethodsmetadata.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;
}
Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;
}对BeanPostProcessor的实现主要在before方法中该方法主要就是两部分内容第一部分主要是将信息封装到LifecycleMetadata中便于后面第二步的执行相关初始化方法。 案例 public class BeanPostProcessorDemo2 {public static void main(String[] args) {// 创建基础容器DefaultListableBeanFactory beanFactory new DefaultListableBeanFactory();// 构建BeanDefinition并注册AbstractBeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition(Person.class).getBeanDefinition();beanFactory.registerBeanDefinition(person,beanDefinition);// 注册CommonAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor new CommonAnnotationBeanPostProcessor();beanFactory.addBeanPostProcessor(commonAnnotationBeanPostProcessor);// 获取BeanPerson person beanFactory.getBean(Person.class);System.out.println(person);}
}class Person{PostConstructpublic void annotationInitMethod(){System.out.println(PostConstruct);}
} 上面的代码定义了一个Person类并使用PostConstruct标记出它的初始化方法然后创建BeanFactory并创建Person的BeanDefinition将其注册到BeanFactory与读取配置文件一样然后创建CommonAnnotationBeanPostProcessor并将其添加到BeanFactory中。 最后打印结果会打印出PostConstruct。如果我们将下面这句代码注释。 beanFactory.addBeanPostProcessor(commonAnnotationBeanPostProcessor); 再次执行可以发现PostConstruct将会失效且最后不会打印出结果。 四、BeanPostProcessor中的顺序性 BeanPostProcessor是可以注册多个的在AbstractBeanFactory内部通过List变量beanPostProcessors来存储BeanPostProcessor。而在执行时是按照List中BeanPostProcessor的顺序一个个执行的所以我们在想容器中添加BeanPostProcessor时需要注意顺序。如果我们不是通过手动添加大多数时候不是时而是在代码或者配置文件中定义多个BeanPostProcessor时我们可以通过实现Ordered接口来控制它的顺序。 BeanPostProcessor依赖的Bean是不会执行BeanPostProcessor的这是因为在创建BeanPostProcessor时其所依赖的Bean就需要完成初始化而这个时候BeanPostProcessor都还未完初始化完成。 此外我们需要了解PostConstruct 执行点(beforeInitialization) 要早于 afterProperitesSet(invokeInitMethod-1) 早于对应的Bean定义的initMethodinvokeinitiMethod-2方法的执行。 案例
public class App3 {public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext();context.scan(com.buydeem.beanpostprocessor);context.register(App3.class);context.refresh();}
}Component
class ClassA{
}Component
class ClassB{
}Component
class MyBeanPostProcessor implements BeanPostProcessor{Autowiredprivate ClassA classA;Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(MyBeanPostProcessorbean);return bean;}
}注意最后ClassA是不会打印出来的而ClassB是会被打印出来。因为MyBeanPostProcessor依赖了ClassA实例ClassA会先初始化完成。 五、总结 Spring中BeanPostProcessor的子接口或实现类有很多种例如InstantiationAwareBeanPostProcessor、MergedBeanDefinitionPostProcessor、DestructionAwareBeanPostProcessor等。 这些接口分别处在Spring Bean生命周期的不同阶段而他们的功能与BeanPostProcessor都类似都是为了给Spring Bean各个生命周期提供扩展点。