前言
SpringBoot框架在设计之初,为了有更好的兼容性,在不同的运行阶,段提供了非常多的扩展点,可以让程序员根据自己的需求,在整个Spring应用程序运行过程中执行程序员自定义的代码。
ApplicationContextInitializer
IOC容器创建完之后执行,可以对上下文环境做一些操作,例如运行环境属性注册等
使用
- 自定义类,实现ApplicationContextInitializer接口
- 在META-INF/spring.factories配置文件中配置自定义的类
示例
自定义类
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
// ioc容器对象创建完毕后执行
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
// 给上下文context对象注入环境属性
// 1.准备属性
Map<String, Object> myMap = new HashMap<>();
myMap.put("applicationName", "lxx666");
// 2.获取属性资源管理对象
// 获取环境对象
ConfigurableEnvironment environment = applicationContext.getEnvironment();
// 属性资源管理对象
MutablePropertySources propertySources = environment.getPropertySources();
// 3.注册
propertySources.addLast(new MapPropertySource("myMap",myMap));
}
}
配置自定义的类,位置:src/main/resources/META-INF/spring.factories
# 接口全路径名称=自定义类全路径名称
org.springframework.context.ApplicationContextInitializer = com.lxx.Initializer.MyApplicationContextInitializer
测试
@SpringBootApplication
public class SpringbootInterviewApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
String applicationName = context.getEnvironment().getProperty("applicationName");
System.out.println(applicationName);
}
}
结果
lxx666
ApplicationListener
监听容器发布的事件,运行程序员执行自己的代码,完成事件驱动开发,它可以监听容器初始化完成,初始化失败等事件,通常情况下可以使用监听器加载资源,开启定时任务等
使用
- 自定义类,实现ApplicationListener接口
- 在META-INF/spring.factories配置文件中配置自定义的类
示例
自定义类
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
// ApplicationEvent event 对应的就是发布的事件,ApplicationReadyEvent,ApplicationFailedEvent
if (event instanceof ApplicationReadyEvent) {
// 容器初始化成功
System.out.println("MyApplicationListener...容器初始化成功...");
}
if (event instanceof ApplicationFailedEvent) {
// 容器初始化成功
System.out.println("MyApplicationListener...容器初始化失败...");
}
}
}
配置自定义的类,位置:src/main/resources/META-INF/spring.factories
org.springframework.context.ApplicationListener = com.lxx.listener.MyApplicationListener
测试
@SpringBootApplication
public class SpringbootInterviewApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
}
}
结果
MyApplicationListener...容器初始化成功...
BeanFactory
Bean容器的根接口,提供Bean对象的创建、配置、依赖注入等功能
AnnotationConfigServletWebServerApplicationContext -> DefaultListableBeanFactory
最终得到的容器类型AnnotationConfigServletWebServerApplicationContext
调用容器的getBean()时,底层是调用了DefaultListableBeanFactory的getBean()。
@SpringBootApplication
public class SpringbootInterviewApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
context.getBean(SpringbootInterviewApplication.class);
}
}
它们之间存在一种委托关系
BeanDefinition
用于描述Bean,包括Bean的名称,Bean的属性,Bean的行为,实现的接口,添加的注解等等。Spring中,Bean在创建之前,都需要封装成对应的BeanDefinition,然后根据BeanDefinition进一步创建Bean对象
示例
// Bean对应的信息会封装到ScannedGenericBeanDefinition
@Component
public class Student {
}
// Bean对应的信息会封装到ConfigurationClassBeanDefinition
@Configuration
public class MyConfig {
@Bean
public String aa() {
return "lxx666";
}
}
@SpringBootApplication
public class SpringbootInterviewApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
// 获取BeanDefinition对象
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
BeanDefinition stuBdf = beanFactory.getBeanDefinition("student");
BeanDefinition aaBdf = beanFactory.getBeanDefinition("aa");
System.out.println(stuBdf.getClass());
System.out.println(aaBdf.getClass());
}
}
结果
class org.springframework.context.annotation.ScannedGenericBeanDefinition
class org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition
BeanFactoryPostProcessor
Bean工厂后置处理器,当BeanFactory准备好之后(Bean初始化之前)会调用该接口的postProcessBeanFactory方法,经常用于新增BeanDefinition
SpringBoot内置的BeanFactoryPostProcessor
实现类名 | 作用 |
---|---|
ConfigurationClassPostProcessor | 扫描启动类所在包下的注解 |
ServletComponentRegisteringPostProcessor | 扫描@WebServlet、@WebFilter、@WebListener |
CachingMetadataReaderFactoryPostProcessor | 配置ConfigurationClassPostProcessor |
ConfigurationWarningsPostProcessor | 配置警告提示 |
示例
public class Teacher {
}
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
// 当BeanFactory实例化好之后(bean创建之前),回调这个函数,注册一些BeanDefinition
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 注册一个Teacher的BeanDefinition
GenericBeanDefinition gbdf = new GenericBeanDefinition();
gbdf.setBeanClass(Teacher.class);
// 向下强转
DefaultListableBeanFactory dbf = (DefaultListableBeanFactory) beanFactory;
// 注册
dbf.registerBeanDefinition("teacher", gbdf);
}
}
@SpringBootApplication
public class SpringbootInterviewApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
Object teacher = context.getBean("teacher");
System.out.println(teacher);
}
}
结果
com.lxx.processor.Teacher@43982337
Aware
感知接口,Spring提供的一种机制,通过实现该接口,重写方法,可以感知Spring应用程序执行过程中的一些变化。Spring会判断当前的Bean有没有实现Aware接口,如果实现了,会在特定的时机回调接口中对应的方法
子接口名 | 作用 |
---|---|
BeanNameAware | Bean名称的感知接口 |
BeanClassLoaderAware | Bean类加载器的感知接口 |
BeanFactoryAware | Bean工厂的感知接口 |
实例
@Component
public class Lxx implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("lxx...setBeanClassLoader..." + classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("lxx...setBeanFactory..." + beanFactory);
}
@Override
public void setBeanName(String name) {
System.out.println("lxx...setBeanName..." + name);
}
}
结果
lxx...setBeanName...lxx
lxx...setBeanClassLoader...jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
lxx...setBeanFactory...org.springframework.beans.factory.support.DefaultListableBeanFactory@38f116f6
InitializingBean/DisposableBean
初始化接口,当Bean被实例化好后,会回调里面的函数,经常用于做一些加载资源的工作
销毁接口,当Bean被销毁之前,会回调里面的函数,经常用于做一些释放资源的工作
实例
@Component
public class Animal implements InitializingBean, DisposableBean {
// 销毁方法
@Override
public void destroy() throws Exception {
System.out.println("Animal...destroy");
}
// 初始化方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Animal...afterPropertiesSet");
}
// @PostConstruct @PreDestroy 注解提供初始化和销毁方法
}
BeanPostProcessor
Bean的后置处理器,当Bean对象初始化之前以及初始化之后,会回调该接口对应的方法
- postProcessBeforeInitialization:Bean对象初始化之前调用
- postProcessAfterInitialization:Bean对象初始化之后调用
SpringBoot内置的BeanPostProcessor
实现类名 | 作用 |
---|---|
AutowiredAnnotationBeanPostProcessor | 用来完成依赖注入 |
AbstractAutoProxyCreator | 用来完成代理对象的创建 |
AbstractAdvisingBeanPostProcessor | 将aop中的通知作用于特定的bean上 |
示例
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
// Bean对象初始化之前调用
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor...postProcessBeforeInitialization..."+beanName);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
// Bean对象初始化之后调用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor...postProcessAfterInitialization..."+beanName);
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}