摘要:即,的后置处理器,它的作用就是在的初始化方法前跟后进行拦截处理。如何注册后置处理器我们暂不作分析,着重说一下,后置处理器是如何工作的。
BeanPostProcessor即,Bean的后置处理器,它的作用就是在Bean的初始化方法前跟后进行拦截处理。我们都知道,要想在Bean的初始化方法前后进行工作,那必须在Bean实例创建完成之后,init方法执行之前,后置处理器就已经在容器中了,所以我们来到向容器中添加后置处理器的类AbstractApplicationContext,其中refresh()中的registerBeanPostProcessors(beanFactory)就是首先向容器中注册我们所需要的所有后置处理器。如何注册后置处理器我们暂不作分析,着重说一下,后置处理器是如何工作的。代码实现
实现类:
@Component public class BeanPostProcessorImpl implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 返回一个传过来的对象 // 在初始化方法调用之前进行后置处理工作 // 什么时候调用呢?在init-method方法之前就调用了 System.out.println("postProcessBeforeInitialization======" + beanName + "======" + bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization======" + beanName + "======" + bean); return bean; } }
配置类:
@Configuration @ComponentScan("com.nmys.story.springCore.springioc.beanpostprocessor_") public class Config01 { @Bean(initMethod = "init",destroyMethod = "destroy") public Train train(){ return new Train(); } }
实体类:
/** * @author 70KG * @Title: Train * @Description: * @date 2018/7/23下午11:31 * @From www.nmyswls.com */ public class Train { private String name = "火车"; private Integer length = 150; public Train() { System.out.println("Train构造方法执行。。。。。。"); } public void init() { System.out.println("Train的init方法执行。。。。。。"); } public void destroy() { System.out.println("Train的destroy方法执行。。。。。。"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getLength() { return length; } public void setLength(Integer length) { this.length = length; } }
测试类:
public class Test01 { @Test public void test() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config01.class); ac.close(); } }
打印结果:
Train构造方法执行。。。。。。 postProcessBeforeInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb Train的init方法执行。。。。。。 postProcessAfterInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb Train的destroy方法执行。。。。。。
结果分析:
首先Train构造方法执行创建对象,然后执行了后置处理器的Before方法,然后才调用init方法,init方法执行完成,再执行后置处理器的After方法,最后容器关闭执行销毁方法。BeanPostProcessor原理分析
AnnotationConfigApplicationContext构造方法中的refresh(); -> AbstractApplicationContext550行finishBeanFactoryInitialization(beanFactory);完成剩余Bean的初始化工作 -> AbstractApplicationContext869行beanFactory.preInstantiateSingletons(); -> DefaultListableBeanFactory760行getBean(beanName); -> AbstractBeanFactory317行createBean(beanName, mbd, args); -> AbstractAutowireCapableBeanFactory503行doCreateBean(beanName, mbdToUse, args); -> AbstractAutowireCapableBeanFactory580行populateBean(beanName, mbd, instanceWrapper);在执行初始化之前,首先给实例赋值 -> AbstractAutowireCapableBeanFactory581行exposedObject = initializeBean(beanName, exposedObject, mbd);准备执行初始化方法 -> AbstractAutowireCapableBeanFactory1700行wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); -> AbstractAutowireCapableBeanFactory1704行invokeInitMethods(beanName, wrappedBean, mbd); -> AbstractAutowireCapableBeanFactory1712行wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
分析AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法:
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
首先获取到所有的后置处理器getBeanPostProcessors()
在for循环中依次调用后置处理器的方法beanProcessor.postProcessBeforeInitialization(result, beanName);
进入postProcessBeforeInitialization方法(这个方法必须在debug过程中才可以进入)
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction
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) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }
来到ApplicationContextAwareProcessor类的79行,首先判断此bean是不是各种的Aware,如果是它列举的那几个Aware就获取Bean工厂的权限,可以向容器中导入相关的上下文环境,目的是为了Bean实例能够获取到相关的上下文,如果不是(显然它也不是)它列举的几个Aware,那就调用invokeAwareInterfaces(bean),向容器中添加相关接口的上下文环境,显然我们自己的实现类也不属于Aware接口,所以这个处理结果直接将Bean返回,不做任何处理。ok,这样初始化之前的方法就分析完了,初始化之后的方法跟前面的流程一模一样。
总结BeanPostProcessor就是在Bean实例创建之后,在进行populateBean赋值之后,init初始化方法之前进行一次调用,init方法之后进行一次调用,这样一来,整个Bean的生命周期,全部掌控在了Spring之下,包括Bean实例创建new Instance(),赋值前后populateBean(),初始化前后init(),销毁前后destroy()。从此Bean便身不由己了。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/73224.html
摘要:也是属于方法调用栈的一环,进去有类似一段伪代码这段代码通过遍历得到所有的,然后挨个执行重写的方法,倘若有一个方法返回的为,那么循环就会跳出,意味着下面的方法不会被执行。 Spring源码原理篇--容器初始化&Bean后置处理器 本篇主要是讲解IOC容器初始化过程中大体进行了哪一些工作,以及Bean后置处理器的工作原理和BeanPostProcessor在底层的使用。 环境准备 编译器...
摘要:本文是容器源码分析系列文章的第一篇文章,将会着重介绍的一些使用方法和特性,为后续的源码分析文章做铺垫。我们可以通过这两个别名获取到这个实例,比如下面的测试代码测试结果如下本小节,我们来了解一下这个特性。 1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本。经过十几年的迭代,现在的 Spring 框架已经非常成熟了...
摘要:在上文中,我实现了一个很简单的和容器。比如,我们所熟悉的就是在这里将切面逻辑织入相关中的。初始化的工作算是结束了,此时处于就绪状态,等待外部程序的调用。其中动态代理只能代理实现了接口的对象,而动态代理则无此限制。 1. 背景 本文承接上文,来继续说说 IOC 和 AOP 的仿写。在上文中,我实现了一个很简单的 IOC 和 AOP 容器。上文实现的 IOC 和 AOP 功能很单一,且 I...
摘要:如果依赖靠构造器方式注入,则无法处理,直接会报循环依赖异常。光继承这个接口还不够,继承这个接口只能获取,要想让生效,还需要拿到切面对象包含和才行。有了目标对象,所有的切面类,此时就可以为生成代理对象了。 Spring 是一个轻量级的 J2EE 开源框架,其目标是降低企业级应用开发难度,提高企业级应用开发效率。在日程开发中,我们会经常使用 Spring 框架去构建应用。所以作为一个经常使...
摘要:关于创建实例的过程,我将会分几篇文章进行分析。源码分析创建实例的入口在正式分析方法前,我们先来看看方法是在哪里被调用的。时,表明方法不存在,此时抛出异常。该变量用于表示是否提前暴露单例,用于解决循环依赖。 1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑。对于已实例化好的单例 bean,getBean(String) ...
阅读 1748·2021-09-03 10:50
阅读 1304·2019-08-30 15:55
阅读 3342·2019-08-30 15:52
阅读 1200·2019-08-30 15:44
阅读 887·2019-08-30 15:44
阅读 3280·2019-08-30 14:23
阅读 3524·2019-08-28 17:51
阅读 2255·2019-08-26 13:52