zoukankan      html  css  js  c++  java
  • 八、spring生命周期之BeanPostProcessor

    BeanPostProcessor我们一般称为Bean的后置处理器,它与我们前面介绍的InitialingBeaninit-method等一样,都是在bean的初始化时被调用,具体的用法我们在举例中进行学习。

    要使用BeanPostProcessor非常简单,只要实现这个接口即可。

    在此之前,我们来先看下我们的Cat类,我们的目的是将这个Cat注册进spring的ioc容器中,并让这个BeanPostProcessor起到作用。

    public class Cat implements InitializingBean,DisposableBean {
    	
    	public Cat(){
    		System.out.println("cat constructor...");
    	}
    
    	@Override
    	public void destroy() throws Exception {
    		// TODO Auto-generated method stub
    		System.out.println("cat...destroy...");
    	}
    
    	@Override
    	public void afterPropertiesSet() throws Exception {
    		// TODO Auto-generated method stub
    		System.out.println("cat...afterPropertiesSet...");
    	}
    	
    	
    	//对象创建并赋值之后调用
    	@PostConstruct
    	public void initMethod(){
    		System.out.println("Cat....@PostConstruct...");
    	}
    	
    	//容器移除对象之前
    	@PreDestroy
    	public void detoryMethod(){
    		System.out.println("Cat....@PreDestroy...");
    	}
    	
    	public void initCat() {
    		System.out.println("Cat.initCat()......");
    	}
    	
    	public void cleanup() {
    		System.out.println("Cat.cleanup()......");
    	}
    }
    

    再来看下我们的配置类

    @Configuration
    public class MainConfigOfLifeCycle {
    	
    //	@Scope("prototype")
    	@Bean(initMethod="initCat",destroyMethod="cleanup")
    	public Cat cat(){
    		return new Cat();
    	}
    	
    	@Bean
    	public MyBeanPostProcessor myBeanPostProcessor() {
    		return new MyBeanPostProcessor();
    	}
    }
    

    结合之前学习过的内容, 就能知道我们为这个Cat类应用了三种初始化及销毁方法,

    分别是@PostConstruct@Predestroy

    还有就是实现 InitializingBean,DisposableBean这两个接口的afterPropertiesSet()destro()方法

    另外就是标注在@Bean(initMethod="initCat",destroyMethod="cleanup")定义的两个方法,也存在于Cat类中,


    现在我们就要加入BeanPostProcessor

    /**
     * 后置处理器:初始化前后进行处理工作
     * 将后置处理器加入到容器中,只需要继承BeanPostProcessor接口并实现其两个方法即可。
     */
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		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;
    	}
    
    }
    
    

    现在一切具备,再写一个测试方法:

    	@Test
    	public void test01(){
    		//1、创建ioc容器
    		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
    		System.out.println("容器创建完成...");
    		
    		//applicationContext.getBean("car");
    		//关闭容器
    		applicationContext.close();
    	}
    
    

    观察控制台打印结果

    cat constructor...// 创建cat对象
    postProcessBeforeInitialization...cat=>com.atguigu.bean.Cat@6591f517 //在所有初始化方法之前被调用
    Cat....@PostConstruct...
    cat...afterPropertiesSet...
    Cat.initCat()......
    postProcessAfterInitialization...cat=>com.atguigu.bean.Cat@6591f517// 在所有初始化方法之后被调用
    容器创建完成...
    Cat....@PreDestroy...// 销毁方法不需要关注
    cat...destroy...
    Cat.cleanup()......
    

    通过上面这个例子,已经很显然BeanPostProcessor的用法,它是在容器中bean初始化前后被调用。


    源码调用分析:

    我们在eclipse中启用debug模式,

    看看这个方法的源码,直接在方法注释中进行分析

    	protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged(new PrivilegedAction<Object>() {
    				@Override
    				public Object run() {
    					invokeAwareMethods(beanName, bean);
    					return null;
    				}
    			}, getAccessControlContext());
    		}
    		else {
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
                // 初始化前调用BeanPostProcessor
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    
    		try {
                //初始化方法
    			invokeInitMethods(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()) {
                // 初始化后调用BeanPostProcessor
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    		return wrappedBean;
    	}
    

    就看到这里,里面内容比较多,可以进invokeInitMethods看看几个初始化方法的调用顺序,JSR-250注解@PostConstruct是如何起作用的等等 ,我们这里只是来源码中找找它在源码中的位置。


    又是一个夜晚,一船的清梦。

    你所看得到的天才不过是在你看不到的时候还在努力罢了!
  • 相关阅读:
    使用FolderBrowserDialog组件选择文件夹
    使用OpenFileDialog组件打开多个文
    使用OpenFileDialog组件打开对话框
    获取弹出对话框的相关返回值
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1137 Final Grading (25 分)
    PAT 甲级 1137 Final Grading (25 分)
  • 原文地址:https://www.cnblogs.com/heliusKing/p/11391271.html
Copyright © 2011-2022 走看看