Spring的BeanFactoryPostProcessor和BeanPostProcessor的使用

BeanFactoryPostProcessor是用来处理修改bean定义信息的后置处理器,这个时候bean还没有初始化,只是定好了BeanDefinition,在BeanFactoryPostProcessor接口的postProcessBeanFactory方法中,我们可以修改bean的定义信息,例如修改属性的值,修改bean的scope为单例或者多例。
BeanPostProcessor则是bean初始化前后对bean的一些操作,意思就是说bean在调用构造之后,初始化方法前后进行一些操作。

BeanPostProcessor

public interface BeanPostProcessor {
//初始化调用方法之前调用(一般我们说来就是initMethod方法或者@PostConstruct注解方法,当然还有其他的方式实现初始化方法),是在构造方法之后执行的
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
//初始化方法之后进行调用
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

进入实现BeanPostProcessor类的方法里面的bean都是已经实例化好的,可以直接用来使用,也就是参数里面的bean可以直接转成我们需要的对象,然后进行属性操作,例如你可以在这里对bean进行设置值,一般来说我们都是在用自定义注解的时候会判断这些bean的字段是否包含我们的自定义注解,当然了还有其他的一些用途,看自己怎么使用了。这里需要主要的一点是在高版本的BeanPostProcessor这个接口,都使用了default实现了默认写法。

BeanFactoryPostProcessor

@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	 //这个是所有的bean的定义信息定义好之后,初始化前的最后一次提供修改的操作,这里一般都是用来修改bean的定义信息或者修改bean的属性用的,这个接口没有提供默认的实现方法,它是一个void方法
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

下面写两个测试类进行测试

package com.madman.annotation.springextension;

import com.madman.annotation.entity.Blue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * 
 * 【类型】: MyBeanPostProcesser 
* 【作用】: 请填写此类的作用
* 【时间】:2019/1/3 17:29
* 【作者】:madman
*
*/ @Configuration @Component public class MyBeanFactoryPostProcesser implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //这种方法尽量不要用,这里获取Bean的时候会把对象对实例化掉,正常来说这里只是bean的定义信息 //https://www.jianshu.com/p/3d099ea43b0e //Blue bule_01 = beanFactory.getBean("bule_01", Blue.class); //InitializingBean BeanDefinition bule_01 = beanFactory.getBeanDefinition("bule_01"); bule_01.getPropertyValues().add("name", "哈哈哼哼"); bule_01.setScope(BeanDefinition.SCOPE_SINGLETON); // bule_01.setInitMethodName(); System.out.println("BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用..."); } }

自定义一个BeanFactoryPostProcessor接口的实现类,并在里面修改了bean的scope属性,还可以修改initMethod方法,关于bean的定义信息这里都可以修改,但是这里也做一个操作的操作,就是Blue bule_01 = beanFactory.getBean("bule_01", Blue.class);前面已经提到过BeanFactoryPostProcessor是提供给你修改的bean的定义信息的口子,也就是修改BeanDefinition对象的属性,如果在这里getBean(""),就会把bean的初始化信息给提前了,这破坏了spring的封装特性,使用BeanFactoryPostProcessor——这种姿势不要用

MyBeanPostProcesser
自定义BeanPostProcessor

package com.madman.annotation.springextension;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

/**
 * 
 * 【类型】: MyBeanPostProcesser 
* 【作用】: 请填写此类的作用
* 【时间】:2019/1/3 17:29
* 【作者】:madman
*
*/ @Configuration @Component public class MyBeanPostProcesser implements BeanPostProcessor { @Nullable @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName的名字是:" + beanName + ",BeanPostProcessor的postProcessBeforeInitialization方法正在调用..."); return bean; } @Nullable @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName的名字是:" + beanName + ",BeanPostProcessor的postProcessAfterInitialization方法正在调用..."); return bean; } }

这里就是简单打印一个日志。
Blue
Blue是也个entity对象,用来测试的。

package com.madman.annotation.entity;

import javax.annotation.PostConstruct;

public class Blue {
    public String name;
    public Integer age;

    @PostConstruct
    public void cc() {
        System.out.println("cc方法执行了,PostConstruct()注解驱动的啦");
    }

    public Blue() {
        System.out.println("无参数构造函数");
    }

    public Blue(String name, Integer age) {
        System.out.println("调用有参数构造方法...");
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Blue{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

CustomBeanDefinitionRegistryPostProcessor
这是一个辅助类,用来自定义bean注册的,就是用来定义bean的,只是没有用平常的那种方式,@Bean或者xml配置。

package com.madman.annotation.springextension;

import com.madman.annotation.entity.Blue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * 
 * 【类型】: CustomBeanDefinitionRegistryPostProcessor 
* 【作用】: 请填写此类的作用
* 【时间】:2019/1/3 14:50
* 【作者】:madman
*
*/ @Configuration @Component public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("自定义的Bean信息...."); BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition("com.madman.annotation.entity.Blue"); beanDefinitionBuilder.addPropertyValue("name", "小鹏一号"); beanDefinitionBuilder.addPropertyValue("age", "18"); BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Blue.class).getBeanDefinition(); beanDefinition.getPropertyValues().add("name", "小鹏二号"); beanDefinition.getPropertyValues().add("age", "28"); registry.registerBeanDefinition("bule_01", beanDefinitionBuilder.getBeanDefinition()); registry.registerBeanDefinition("bule_02", beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }

然后写一个测试方法

package com.madman.annotation.start;
import com.madman.annotation.config.Config_1;
import com.madman.annotation.entity.Blue;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Map;
public class start_1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotation = new AnnotationConfigApplicationContext(Config_1.class);
        Map beansOfType = annotation.getBeansOfType(Blue.class);
        for (String s : beansOfType.keySet()) {
            System.out.println("名字是:" + s);
            System.out.println(beansOfType.get(s).toString());
        }
    }
}

结果

BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用...
beanName的名字是:config_1,BeanPostProcessor的postProcessBeforeInitialization方法正在调用...
beanName的名字是:config_1,BeanPostProcessor的postProcessAfterInitialization方法正在调用...
无参数构造函数
beanName的名字是:bule_01,BeanPostProcessor的postProcessBeforeInitialization方法正在调用...
cc方法执行了,PostConstruct()注解驱动的啦
beanName的名字是:bule_01,BeanPostProcessor的postProcessAfterInitialization方法正在调用...
无参数构造函数
beanName的名字是:bule_02,BeanPostProcessor的postProcessBeforeInitialization方法正在调用...
cc方法执行了,PostConstruct()注解驱动的啦
beanName的名字是:bule_02,BeanPostProcessor的postProcessAfterInitialization方法正在调用...
名字是:bule_01
Blue{name='哈哈哼哼', age=18}
名字是:bule_02
Blue{name='小鹏二号', age=28}

根据结果来看一下顺序是否正确。
BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用…
这句话是在MyBeanFactoryPostProcesser方法里面打印出来的,说明它的执行顺序的最前面的,我们说的这个是bean初始化前的最后一次提供修改的机会。
beanName的名字是:config_1,BeanPostProcessor的postProcessBeforeInitialization方法正在调用…
beanName的名字是:config_1,BeanPostProcessor的postProcessAfterInitialization方法正在调用…
上面这两行是一个configuration配置类,这里可以忽略。
无参数构造函数
beanName的名字是:bule_01,BeanPostProcessor的postProcessBeforeInitialization方法正在调用…
cc方法执行了,PostConstruct()注解驱动的啦
beanName的名字是:bule_01,BeanPostProcessor的postProcessAfterInitialization方法正在调用…
然后这四行是bean的一些初始化操作,首先的调用了构造方法函数,然后调用了postProcessBeforeInitialization的方法,然后调用了@PostConstruct()标注的方法(也就是我们所说的initMethod方法),然后再调用了postProcessAfterInitialization的方法,这个方法的执行顺序是在初始化方法之后的。

名字是:bule_01
Blue{name='哈哈哼哼', age=18}

这个bean的打印结果不是小鹏一号,而是哈哈哼哼,这个哈哈哼哼就是在postProcessBeanFactory这个方法里面获取了bule_01然后修改了他的属性。

 @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //这种方法尽量不要用,这里获取Bean的时候会把对象对实例化掉,正常来说这里只是bean的定义信息
        //https://www.jianshu.com/p/3d099ea43b0e
        //Blue bule_01 = beanFactory.getBean("bule_01", Blue.class);
        //InitializingBean
        BeanDefinition bule_01 = beanFactory.getBeanDefinition("bule_01");
        bule_01.getPropertyValues().add("name", "哈哈哼哼");
        bule_01.setScope(BeanDefinition.SCOPE_SINGLETON);
        // bule_01.setInitMethodName();
        System.out.println("BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用...");
    }

这里就记录一下Spring的BeanFactoryPostProcessor和BeanPostProcessor如何使用。

你可能感兴趣的:(spring学习记录)