Spring让人眼前一亮的11个小技巧( 三 )

这种方式是最灵活的 , 能在registerBeanDefinitions方法中获取到BeanDefinitionRegistry容器注册对象,可以手动控制BeanDefinition的创建和注册 。
6.项目启动时有时候我们需要在项目启动时定制化一些附加功能 , 比如:加载一些系统参数、完成初始化、预热本地缓存等,该怎么办呢?
好消息是springboot提供了:

  • CommandLineRunner
  • ApplicationRunner
这两个接口帮助我们实现以上需求 。
它们的用法还是挺简单的,以ApplicationRunner接口为例:
@Componentpublic class TestRunner implements ApplicationRunner {@Autowiredprivate LoadDataService loadDataService;public void run(ApplicationArguments args) throws Exception {loadDataService.load();}}实现ApplicationRunner接口,重写run方法,在该方法中实现自己定制化需求 。
如果项目中有多个类实现了ApplicationRunner接口,他们的执行顺序要怎么指定呢?
答案是使用@Order(n)注解 , n的值越小越先执行 。当然也可以通过@Priority注解指定顺序 。
7.修改BeanDefinitionSpring IOC在实例化Bean对象之前 , 需要先读取Bean的相关属性 , 保存到BeanDefinition对象中,然后通过BeanDefinition对象,实例化Bean对象 。
如果想修改BeanDefinition对象中的属性,该怎么办呢?
答:我们可以实现BeanFactoryPostProcessor接口 。
@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);beanDefinitionBuilder.addPropertyValue("id", 123);beanDefinitionBuilder.addPropertyValue("name", "苏三说技术");defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition());}}在postProcessBeanFactory方法中,可以获取BeanDefinition的相关对象,并且修改该对象的属性 。
8.初始化Bean前后有时,你想在初始化Bean前后,实现一些自己的逻辑 。
这时可以实现:BeanPostProcessor接口 。
该接口目前有两个方法:
  • postProcessBeforeInitialization 该在初始化方法之前调用 。
  • postProcessAfterInitialization 该方法再初始化方法之后调用 。
例如:
@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof User) {((User) bean).setUserName("苏三说技术");}return bean;}}如果spring中存在User对象,则将它的userName设置成:苏三说技术 。
其实,我们经常使用的注解 , 比如:@Autowired、@Value、@Resource、@PostConstruct等,是通过AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor实现的 。
9.初始化方法目前spring中使用比较多的初始化bean的方法有:
  1. 使用@PostConstruct注解
  2. 实现InitializingBean接口
9.1 使用@PostConstruct注解@Servicepublic class AService {@PostConstructpublic void init() {System.out.println("===初始化===");}}在需要初始化的方法上增加@PostConstruct注解 , 这样就有初始化的能力 。
9.2 实现InitializingBean接口@Servicepublic class BService implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("===初始化===");}}实现InitializingBean接口 , 重写afterPropertiesSet方法 , 该方法中可以完成初始化功能 。
10.关闭容器前有时候,我们需要在关闭spring容器前,做一些额外的工作,比如:关闭资源文件等 。
这时可以实现DisposableBean接口,并且重写它的destroy方法:
@Servicepublic class DService implements InitializingBean, DisposableBean {@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean destroy");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean afterPropertiesSet");}}这样spring容器销毁前 , 会调用该destroy方法,做一些额外的工作 。
通常情况下,我们会同时实现InitializingBean和DisposableBean接口 , 重写初始化方法和销毁方法 。
11.自定义作用域我们都知道spring默认支持的

推荐阅读