springboot BeanFactoryPostProcessor与BeanPostProcessor
***********************
相关类与接口
BeanFactoryPostProcessor:对象实例化前调用,可修改beanDefinition
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
ConfigurableListableBeanFactory
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
Iterator<String> getBeanNamesIterator();
boolean isConfigurationFrozen();
boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;
void ignoreDependencyType(Class<?> var1);
void ignoreDependencyInterface(Class<?> var1);
void registerResolvableDependency(Class<?> var1, @Nullable Object var2);
void clearMetadataCache();
void freezeConfiguration();
void preInstantiateSingletons() throws BeansException;
}
BeanDefinition
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setRole(int var1);
void setScope(@Nullable String var1);
void setDependsOn(@Nullable String... var1);
void setDescription(@Nullable String var1);
int getRole();
String getScope();
String[] getDependsOn();
String getDescription();
void setParentName(@Nullable String var1);
void setBeanClassName(@Nullable String var1);
void setFactoryBeanName(@Nullable String var1);
void setFactoryMethodName(@Nullable String var1);
void setInitMethodName(@Nullable String var1);
void setDestroyMethodName(@Nullable String var1);
String getParentName();
String getBeanClassName();
String getFactoryBeanName();
String getFactoryMethodName();
String getInitMethodName();
String getDestroyMethodName();
void setPrimary(boolean var1);
void setLazyInit(boolean var1);
void setAutowireCandidate(boolean var1);
boolean isPrimary();
boolean isLazyInit();
boolean isAutowireCandidate();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !this.getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !this.getPropertyValues().isEmpty();
}
ResolvableType getResolvableType();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
AttributeAccessor
public interface AttributeAccessor {
String[] attributeNames();
boolean hasAttribute(String var1);
void setAttribute(String var1, @Nullable Object var2);
Object getAttribute(String var1);
Object removeAttribute(String var1);
default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
Assert.notNull(name, "Name must not be null");
Assert.notNull(computeFunction, "Compute function must not be null");
Object value = this.getAttribute(name);
if (value == null) {
value = computeFunction.apply(name);
Assert.state(value != null, () -> {
return String.format("Compute function must not return null for attribute named '%s'", name);
});
this.setAttribute(name, value);
}
return value;
}
}
BeanPostProcessor:对象初始化前后调用
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;
} //对象初始化后调用
}
***********************
示例
******************
pojo 层
Person
@Data
public class Person {
private String name;
private Integer age;
}
Student
@Data
public class Student {
private String name;
private Integer age;
}
******************
config 层
DataConfig
@Configuration
public class DataConfig {
@Bean("person")
public Person initPerson(){
Person person=new Person();
person.setName("海贼王");
person.setAge(20);
return person;
}
@Bean("student")
public Student initStudent(){
Student student=new Student();
student.setName("瓜田李下");
student.setAge(20);
return student;
}
}
CustomBeanFactoryPostProcessor
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
BeanDefinition beanDefinition=configurableListableBeanFactory.getBeanDefinition("person");
System.out.println(beanDefinition);
String[] s=configurableListableBeanFactory.getBeanDefinitionNames();
List<String> list=Arrays.asList(s);
if (list.contains("person")){
System.out.println(true);
}
System.out.println(beanDefinition.hasPropertyValues());
MutablePropertyValues propertyValues=beanDefinition.getPropertyValues();
System.out.println(propertyValues);
PropertyValue[] p=propertyValues.getPropertyValues();
System.out.println(p.length);
System.out.println(propertyValues.contains("name"));
propertyValues.removePropertyValue("name");
propertyValues.add("name","瓜田李下");
System.out.println(propertyValues);
} //添加的name属性,在populateBean()时设置,替换原来的属性("海贼王")
}
CustomBeanPostProcessor:对所有bean初始化前后都做处理
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Student || bean instanceof Person){
System.out.println(beanName+"调用postProcessBeforeInitialization");
System.out.println(bean);
}
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Student || bean instanceof Person){
System.out.println(beanName+"调用postProcessBeforeInitialization");
System.out.println(bean+"\n");
}
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
******************
controller 层
HelloController
@RestController
public class HelloController {
@Resource
private Person person;
@Resource
private Student student;
@RequestMapping("/hello")
public String hello(){
System.out.println(person);
System.out.println(student);
return "success";
}
}
***********************
测试输出
启动后,控制台输出
true
false
PropertyValues: length=0
0
false
PropertyValues: length=1; bean property 'name'
2021-08-04 22:52:39.308 INFO 2380 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-08-04 22:52:39.318 INFO 2380 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-08-04 22:52:39.318 INFO 2380 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.50]
2021-08-04 22:52:39.322 INFO 2380 --- [ main] o.a.catalina.core.AprLifecycleListener : An older version [1.2.23] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [1.2.30]
2021-08-04 22:52:39.323 INFO 2380 --- [ main] o.a.catalina.core.AprLifecycleListener : Loaded Apache Tomcat Native library [1.2.23] using APR version [1.7.0].
2021-08-04 22:52:39.323 INFO 2380 --- [ main] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [false].
2021-08-04 22:52:39.323 INFO 2380 --- [ main] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2021-08-04 22:52:39.329 INFO 2380 --- [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1c 28 May 2019]
2021-08-04 22:52:39.481 INFO 2380 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-08-04 22:52:39.482 INFO 2380 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1145 ms
person调用postProcessBeforeInitialization
Person(name=瓜田李下, age=20)
person调用postProcessBeforeInitialization
Person(name=瓜田李下, age=20)
//populateBean()后,name属性已经修改为瓜田李下
//postProcessBeforeInitialization、
//postProcessBeforeInitialization均在populateBean之后调用
student调用postProcessBeforeInitialization
Student(name=瓜田李下, age=20)
student调用postProcessBeforeInitialization
Student(name=瓜田李下, age=20)
localhost:8080/hello,控制台输出:
2021-08-04 23:01:35.354 INFO 12920 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-08-04 23:01:35.354 INFO 12920 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
Person(name=瓜田李下, age=20)
Student(name=瓜田李下, age=20)