天天看點

Spring Boot使用BeanPostProcessor-後置處理器對Bean進行攔截,改造Bean或做一些邏輯業務

前面我們介紹了一些方式定制Bean的生命周期,這篇部落格将介紹如何在把Bean注入容器之前攔截,再根據需求做一些操作。

  • 建立類實作BeanPostProcessor接口,并重寫方法。使用@Component注解,把其注入容器(這樣Processor才能起作用)。:
import com.michael.annotation.demo.POJO.Module;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("Module1")){
            ((Module)bean).setName("Java Programming");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("The postProcessAfterInitialization method is calling.");
        return bean;
    }
}
           
  • 測試代碼:
import com.michael.annotation.demo.POJO.Module;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

import static java.lang.System.out;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
        out.println("The container has been initialized.");
        for(String name : applicationContext.getBeanDefinitionNames()){
            if(!name.contains("."))
                out.println(name);
        }

        //print the module'name which is set when postProcessBeforeInitialization method is calling.
        out.println(((Module)applicationContext.getBean("Module1")).getName());

        out.println("The container has been destroyed.");
    }
}
           
  • 輸出:
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The Module Bean is being created.
The postConstruct method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
The postProcessAfterInitialization method is calling.
2020-03-25 16:23:35.478  INFO 28179 --- [           main] c.m.annotation.demo.DemoApplication      : Started DemoApplication in 0.636 seconds (JVM running for 0.93)
The container has been initialized.
demoApplication
test
myBeanPostProcessor
myConfig
personService
Module1
propertySourcesPlaceholderConfigurer
taskExecutorBuilder
applicationTaskExecutor
taskSchedulerBuilder
Java Programming
The container has been destroyed.
The preDestroy method is calling.

Process finished with exit code 0
           
  • 從輸出可以看出BeanPostProcessor-後置處理器裡面的方法在所有Bean被注入前後都被調用了一遍, 我們可以了解為filter所有Bean。
  • ID為"Module1"的Bean被攔截後,設定了其name屬性,在main方法中被列印出來。
  • 在學習Spring Boot的過程中,越發感覺AOP和IOC是Spring的核心。

繼續閱讀