spring后置处理器BeanPostProcessor

BeanPostProcessor的作用是在调用初始化方法的前后添加一些逻辑,这里初始化方法是指在配置文件中配置init-method,或者实现了InitializingBean接口的afterPropertiesSet方法,注意不包括@PostConstruct这种初始化方式。可以看源码AbstractAutowireCapableBeanFactory类中的invokeInitMethods方法。

1.用法

新建Student类

package com.demo.spring.entity;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

/**
 * @author chenyk
 * @date 2018年5月8日
 */
@Component("student")
public class Student{
    private String name;
    private int age;
    
    private School school;
    
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public School getSchool() {
        return school;
    }
    public void setSchool(School school) {
        this.school = school;
    }
    
    
    public void init(){
        System.out.println("执行 init方法");
    }

}

创建实现了BeanPostProcessor接口的后置处理器StudentBeanPostProcessor

package com.demo.spring.entity;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * Bean后置处理器
 * @author chenyk
 * @date 2018年6月29日
 */

//以下这两个方法不能返回null,否则在调用初始化方法时会报空指针异常;因为后置处理器从springIOC容器中取出bean实例后需要再把bean实例放回去 public class StudentBeanPostProcessor implements BeanPostProcessor{ /** * 在bean实例调用初始化方法之前调用 */ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(beanName.equals("student")){ System.out.println("开始调用init方法"); } return bean; } /** * 在bean实例调用初始化方法之后调用 */ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(beanName.equals("student")){ System.out.println("init方法调用结束"); } return bean; } }

在配置文件aop.xml中添加以下信息

<bean id="student" class="com.demo.spring.entity.Student" init-method="init" >
        <property name="name" value="张三"></property>
</bean>
<!-- spring会自动检测实现了BeanPostProcessor接口的类,并将其注册为后置处理器 --> <bean id="studentBeanPostProcessor" class="com.demo.spring.entity.StudentBeanPostProcessor" />

测试方法

@Test
    public void testAop5(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop.xml");        
    }

看下打印信息:

开始调用init方法
2018-07-02 13:58:47,519 DEBUG [AbstractAutowireCapableBeanFactory.java:1731] : Invoking init method 'init' on bean with name 'student'  //这一行信息,就是即将调用init-method方法的日志打印
执行 init方法
init方法调用结束

需要注意的是,如果一个类实现了BeanPostProcessor接口,那么这个类就作用于所有的bean实例,我们可以在BeanPostProcessor接口的两个方法中添加自己的控制和逻辑;

2.源码分析

2.1 找到实现BeanPostProcessor接口的类,并将其注册为后置处理器,看源码

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);
          //发现注册bean后置处理器,在这个方法中进行 
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

2.2 后置处理器生效的地方,进入AbstractAutowireCapableBeanFactory类中的initializeBean方法

    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;
//后置处理器的postProcessBeforeInitialization方法
if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }      //调用初始化方法有:init-method,实现了InitializingBean接口的方法  try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); }
//后置处理器的postProcessAfterInitialization方法
if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }

猜你喜欢

转载自www.cnblogs.com/51life/p/9254505.html
今日推荐