BeanFactoryPostProcessor和BeanPostProcessor

package com.jd.spring.test.pojo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class Person implements InitializingBean,DisposableBean,BeanNameAware,BeanFactoryAware {
    private String name;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public void setBeanFactory(BeanFactory paramBeanFactory)
            throws BeansException {
        System.out.println("》》》调用了BeanFactoryAware的setBeanFactory方法了");
    }

    @Override
    public void setBeanName(String paramString) {
        System.out.println("》》》调用了BeanNameAware的setBeanName方法了");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("》》》调用了DisposableBean的destroy方法了");        
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("》》》调用了Initailization的afterPropertiesSet方法了");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", sex=" + sex
                + "]";
    }
}


package com.jd.spring.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

/**
 *实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,
 * Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,
 * 并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,
 * 也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,
 * 并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
 注意:BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,
 在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息,
 */
public class FactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("******调用了BeanFactoryPostProcessor");
        String[] beanStr = configurableListableBeanFactory.getBeanDefinitionNames();
        for (String beanName : beanStr) {
            if ("person".equals(beanName)) {
                BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(beanName);
                MutablePropertyValues m = beanDefinition.getPropertyValues();
                if (m.contains("name")) {
                    m.addPropertyValue("name", "赵四");
                    System.out.println("》》》修改了name属性初始值了");
                }
            }
        }
    }

}


package com.jd.spring.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 BeanPostProcessor接口:这个接口是单独成类的,它的作用范围是Spring容器,一旦在容器中配置了这个类,那么该容器中所有bean在初始化的前后都会调用这个接口对应的方法
 */
public class PostProcessor implements BeanPostProcessor{

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后置处理器处理bean=【"+beanName+"】开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后置处理器处理bean=【"+beanName+"】完毕!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
	    http://www.springframework.org/schema/context
	    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <!-- 支持Spring注解 -->
    <!--<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />-->
    <!-- Annotation -->
    <context:annotation-config />
    <context:component-scan base-package="com.jd" />

    <!-- 注册一个BeanPostProcessor -->
    <bean id="postProcessor" class="com.jd.spring.test.processor.PostProcessor"/>
    <!-- 注册一个BeanFactoryPostProcessor -->
    <bean id="factoryPostProcessor" class="com.jd.spring.test.processor.FactoryPostProcessor"/>
    <!-- 普通bean -->
    <bean id="person" class="com.jd.spring.test.pojo.Person">
        <property name="name" value="张三"/>
        <property name="sex" value="男"/>
    </bean>
</beans>

package com.jd.spring.test;


import com.jd.spring.test.pojo.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {

    public static void main(String[] args) {
        System.out.println("》》》Spring ApplicationContext容器开始初始化了......");
        ApplicationContext applicationcontext= new ClassPathXmlApplicationContext(new String[]{"beans.xml"});


        Person person = (Person) applicationcontext.getBean("person");
        System.out.println(person.toString());


        System.out.println("》》》Spring ApplicationContext容器初始化完毕了......");
    }


}

打印结果:

》》》Spring ApplicationContext容器开始初始化了......

        七月 17, 2018 10:48:03 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
        信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@46f7f36a: startup date [Tue Jul 17 22:48:03 CST 2018]; root of context hierarchy
        七月 17, 2018 10:48:03 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
        信息: Loading XML bean definitions from class path resource [beans.xml]


        ******调用了BeanFactoryPostProcessor
        》》》修改了name属性初始值了

        /**
         * 此处为Spring内部的bean 并没有implements InitializingBean,DisposableBean,BeanNameAware,BeanFactoryAware这些接口
         * 所以 只是仅仅走了下BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法
         * BeanPostProcessor接口:这个接口是单独成类的,它的作用范围是Spring容器,一旦在容器中配置了这个类,那么该容器中所有bean在初始化的前后都会调用这个接口对应的方法
         */

        后置处理器处理bean=【org.springframework.context.event.internalEventListenerProcessor】开始
        后置处理器处理bean=【org.springframework.context.event.internalEventListenerProcessor】完毕!
        后置处理器处理bean=【org.springframework.context.event.internalEventListenerFactory】开始
        后置处理器处理bean=【org.springframework.context.event.internalEventListenerFactory】完毕!

        /**
         * Person 实现了BeanNameAware接口的打印效果
         */
        》》》调用了BeanNameAware的setBeanName方法了

        /**
         * Person 实现了BeanFactoryAware接口的打印效果
         */
        》》》调用了BeanFactoryAware的setBeanFactory方法了


        /**
         * 注意:这里虽然Person 没有implements BeanPostProcessor接口 但是仍然会执行BeanPostProcessor接口的
         * 中的postProcessBeforeInitialization方法
         * 因为BeanPostProcessor:bean级别的处理,针对某个具体的bean进行处理 所以每个bean初始化前后 都会走此方法
         * BeanPostProcessor接口:这个接口是单独成类的,它的作用范围是Spring容器,一旦在容器中配置了这个类,
         * 那么该容器中所有bean在初始化的前后都会调用这个接口对应的方法
         */
        后置处理器处理bean=【person】开始


        》》》调用了Initailization的afterPropertiesSet方法了

        /**
         * 注意:这里虽然Person 没有implements BeanPostProcessor接口 但是仍然会执行BeanPostProcessor接口的
         * 中的postProcessAfterInitialization方法
         * 因为BeanPostProcessor:bean级别的处理,针对某个具体的bean进行处理 所以每个bean初始化前后 都会走此方法
         * BeanPostProcessor接口:这个接口是单独成类的,它的作用范围是Spring容器,一旦在容器中配置了这个类,
         * 那么该容器中所有bean在初始化的前后都会调用这个接口对应的方法
         */
        后置处理器处理bean=【person】完毕!

        Person [name=赵四, sex=男]
        》》》Spring ApplicationContext容器初始化完毕了......

        Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/luzhensmart/article/details/81090025