Spring之後置處理器

2022-12-16 18:01:11
 
Spring的後置處理器是Spring對外開發的重要擴充套件點,允許我們接入Bean的範例化流程中,以達到動態註冊BeanDefinition動態修改BeanDefinition動態修改Bean的作用。
 
BeanFactoryPostProcessor
 
BeanFactory的後置處理器,在BeandefinitionMap填充完畢之後,Bean範例化之前執行。
BeanFactoryPostProcessor是一個介面規範,用於對BeanDefinition進行操作(註冊、修改、刪除)。
package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanFactoryPostProcessor

 

應用

  • 方式一:自定義BeanFactoryPostProcessor介面實現類:實現BeanFactoryPostProcessor介面,並將實現類註冊到Spring中,Spring就可以自動呼叫postProcessBeanFactory方法.
package com.blueStarWei.processor;

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.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 註冊
        BeanDefinition definition = new RootBeanDefinition();
        definition.setBeanClassName("com.blueStarWei.ObjectBeanFactory");
        //必須強制轉換為DefaultListableBeanFactory才能註冊\刪除
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
        defaultListableBeanFactory.registerBeanDefinition("myBeanFactory",definition);

        //刪除
        defaultListableBeanFactory.removeBeanDefinition("user");

        //修改
        BeanDefinition person = beanFactory.getBeanDefinition("person");
        person.setScope(BeanDefinition.SCOPE_PROTOTYPE);
    }
}
  • 方式二:自定義BeanDefinitionRegistryPostProcessor介面實現類:BeanDefinitionRegistryPostProcessor介面是BeanFactoryPostProcessor介面的子介面,主要用於註冊BeanDefinition。【先呼叫postProcessBeanDefinitionRegistry(),再呼叫postProcessBeanFactory()】
package com.blueStarWei.processor;

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.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println(">>>>>>>1. postProcessBeanDefinitionRegistry");
        BeanDefinition definition = new RootBeanDefinition();
        definition.setBeanClassName("com.blueStarWei.ObjectBeanFactory");
        registry.registerBeanDefinition("myBeanFactory",definition);
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println(">>>>>>>>>>2. postProcessBeanFactory");
    }
}
注意:當方式一與方式二同時使用時,呼叫順序為:
  • BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()
  • BeanDefinitionRegistryPostProcessor.postProcessBeanFactory()
  • BeanFactoryPostProcessor.postProcessBeanFactory()

 

BeanPostProcessor

Bean的後置處理器,一般在Bean的初始化前後執行。Bean範例化之後,填充到單例池singletonObjects之前執行,會進行Bean的初始化。
BeanPostProcessor是一個介面規範,用於對Bean進行修改
package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

public interface BeanPostProcessor {

   /**
    * 在Bean的初始化之前執行
    */
   Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

   /**
    * 在Bean的初始化之後執行
    */
   Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
BeanPostProcessor

 

應用

  • 使用動態代理進行Bean的功能增強
package com.blueStarWei.processor;

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

import java.lang.reflect.Proxy;

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     * 列印方法呼叫時間紀錄檔 
     * 注意:使用jdk自帶的Proxy只能對有介面的類進行動態代理,直接代理POJO會報型別ClassCastException
     *
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Object beanProxy = Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    long startTime = System.currentTimeMillis();
                    Object result = method.invoke(bean, args);
                    long endTime = System.currentTimeMillis();
                    System.out.println(beanName + "." + method.getName() + "執行時間:" + (endTime - startTime) + "ms.");
                    return result;
                }
        );
        return beanProxy;
    }
}