一.BeanDefinitionRegistryPostProcessor扩展点
1. 重写 postProcessBeanDefinitionRegistry
BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor 需要重写 postProcessBeanDefinitionRegistry 方法
2.获取BeanDefinitionRegistry,增删改BeanDefinition
能过实现 BeanDefinitionRegistryPostProcessor 接口,重写 postProcessBeanDefinitionRegistry 方法 可以拿到 BeanDefinitionRegistry 自己注册bean的定义信息 或者拿到任何一个bean的定义信息进行修改
/**
* 在完成注册bean定义信息后执行
* @param registry
* @throws BeansException
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//拿到bean的定义信息
BeanDefinition beanDefinition = registry.getBeanDefinition("a");
System.out.println("beanDefinition = " + beanDefinition);
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
genericBeanDefinition.setBeanClass(C.class);
HashMap<Object, Object> properMap = new HashMap<>();
properMap.put("name","我是C");
genericBeanDefinition.setPropertyValues(new MutablePropertyValues(properMap));
//注册新的bean定义信息
registry.registerBeanDefinition("c",genericBeanDefinition);
System.out.println("BeanDefinitionRegistryPostProcessor 扩展点 执行 postProcessBeanDefinitionRegistry");
}
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");
C bean = applicationContext.getBean(C.class);
System.out.println("bean = " + bean.getName());
3.执行时机
BeanDefinitionRegistryPostProcessor 执行时间在 创建bean工厂并解析生成bd(BeanDefinition) 之后,执行 BeanFactoryPostProcessor 扩展点之前
二.BeanFactoryPostProcessor 扩展点
1. 重写 postProcessBeanFactory
实现 BeanFactoryPostProcessor 需要重写 postProcessBeanFactory 方法
有非常多的子类 包括我们刚刚看到的 BeanDefinitionRegistryPostProcessor
2. 获取 beanFactory 在bean实例化前对Bean的属性修改
实现BeanFactoryPostProcessor 重写 postProcessBeanFactory 方法
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("c");
beanDefinition.getPropertyValues().addPropertyValue("name","增强c");
System.out.println("BeanFactoryPostProcessor 的 postProcessBeanFactory 方法执行了 拿到bean工厂");
}
对bean的属性name进行修改
可以看到结果是重写postProcessBeanFactory 后设置的值
3.执行时机
BeanFactoryPostProcessor 扩展点 在 解析生成bd,并执行BeanDefinitionRegistryPostProcessor扩展点后,实例化bean之前
三. InstantiationAwareBeanPostProcessor 扩展点
1.重写postProcessBeforeInstantiation和postProcessAfterInstantiation
InstantiationAwareBeanPostProcessor 继承自 BeanPostProcessor 接口 有四个默认方法
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
2.抑制特定目标bean的默认实例化或者属性注入
- postProcessBeforeInstantiation 方法将在 bean实例化前执行,如果返回不为null,将结束当前bean的实例化
- postProcessAfterInstantiation 方法将在bean实例化后属性填充前执行,如果返回为false,将不会进行属性注入
首先我们看一个bean C的正常生命周期
而此时 postProcessBeforeInstantiation 返回值为null
如果我不返回null,创建一个新的C对象返回
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法执行了 在"+beanName+"实例化之前");
if (beanClass.isAssignableFrom(C.class)){
return new C("我是代理C");
}
return null;
}
可以看到此时 执行完 postProcessBeforeInstantiation 返回后 bean的生命周期就结束了,并且容器中的 C 变成了我们返回的对象
再来看 postProcessAfterInstantiation 方法 默认返回true 进行属性注入 如果我们返回false
如果返回false是不是进行属性填充的 因为bean的生命周期中缺少了属性填充 所以bean的name属性没有值
3.执行时机
postProcessBeforeInstantiation 方法将在BeanFactoryPostProcessor 扩展点执行后 bean实例化前执行
postProcessAfterInstantiation 方法将在 bean实例化后,属性填充前执行
四.BeanPostProcessor
1.重写 postProcessBeforeInitialization 和 postProcessAfterInitialization
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
2.生成新的bean实例以及代理类
1.重写 postProcessBeforeInitialization 方法,生成新的bean实例
重写 postProcessBeforeInitialization 方法,返回一个新的c,没有设置属性值
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("c")){
C c = (C) bean;
System.out.println("当前正在初始化的bean的name值为"+c.getName());
C c1 = new C();
return c1;
}
return bean;
}
可以看到此时的bean变成了一个新的bean 注意这个行的bean是不会走Spring中Bean生命周期的其他步骤的,直接就是
new Bean() -> 执行BeanPostProcessor.postProcessAfterInitialization 方法 然后就放到容器中 不会走执行BeanPostProcessor这个扩展点执行时前任何的Spring中bean生命周期过程,包括属性填充
如果 c 依赖 d 且两者都有spring容器管理,则在属性填充时,d会有值 如果没有值,说明没有属性填充
2.重写 postProcessAfterInitialization方法,生成代理类
可以通过重写postProcessAfterInitialization 方法,往容器中添加一个代理类,Spring的AOP就是基于此处实现的
可以看如下的案例演示,此处使用的是JDK动态代理
往容器中添加一个D bean,改bean实现了 Myint 接口 有一个抽象方法 say();
通过实现 BeanPostProcessor 重写 postProcessAfterInitialization 方法,往容器中添加一个代理对象
代理类MyProxy
public class MyProxy {
public Myint proxy(Object target)
{
Myint o = (Myint) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法执行前增强");
Object invoke = method.invoke(target);
System.out.println("方法执行后增强");
return invoke;
}
}
);
return o;
}
}
我们从容器中取出这个对象,并执行say方法
可以看到执行的是代理类的方法,也就是说往容器中添加的是代理类对象
五.总结图
|