前言
SpringBoot框架在设计之初,为了有更好的兼容性,在不同的运行阶,段提供了非常多的扩展点,可以让程序员根据自己的需求,在整个Spring应用程序运行过程中执行程序员自定义的代码。
ApplicationContextInitializer
IOC容器创建完之后执行,可以对上下文环境做一些操作,例如运行环境属性注册等
使用
- 自定义类,实现ApplicationContextInitializer接口
- 在META-INF/spring.factories配置文件中配置自定义的类
示例
自定义类
public class MyApplicationContextInitializer implements ApplicationContextInitializer {// ioc容器对象创建完毕后执行@Overridepublic 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 {@Overridepublic void onApplicationEvent(ApplicationEvent event) {// ApplicationEvent event 对应的就是发布的事件,ApplicationReadyEvent,ApplicationFailedEventif (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 {@Beanpublic 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@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 注册一个Teacher的BeanDefinitionGenericBeanDefinition 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 {@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("lxx...setBeanClassLoader..." + classLoader);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("lxx...setBeanFactory..." + beanFactory);}@Overridepublic 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 {// 销毁方法@Overridepublic void destroy() throws Exception {System.out.println("Animal...destroy");}// 初始化方法@Overridepublic 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对象初始化之前调用@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("MyBeanPostProcessor...postProcessBeforeInitialization..."+beanName);return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}// Bean对象初始化之后调用@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("MyBeanPostProcessor...postProcessAfterInitialization..."+beanName);return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
}