钩子Aware
Spring中有大量的很多Aware接口,给使用者提供ioc容器中各个阶段的感知方式
例如
- ApplicationStartupAware接口的bean就将会在容器启动的时候触发
- BeanFactoryAware将会在给Bean设置beanFactory的时候触发
通过这些钩子函数,使用者能够根据需要,在恰当时机去做某些事,或者拿到需要使用的容器中的对象。
与Bean相关的:
- BeanFactoryAware
- BeanClassLoaderAware
- BeanNameAware
Bean生命周期相关的
改造ServiceA如下:
package com.test.service;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* @author felix
*/
public class ServiceA implements BeanFactoryAware, BeanNameAware, BeanClassLoaderAware {
public ServiceA() {
System.out.println("constructor");
}
@PostConstruct
public void postConstruct() {
System.out.println("post construct");
}
public void init() {
System.out.println("init");
}
public void destroy() {
System.out.println("destroy");
}
@PreDestroy
public void preDestroy() {
System.out.println("preDestroy");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory:" + beanFactory.getClass());
}
public void setBeanName(String beanName) {
System.out.println("setBeanName:" + beanName);
}
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("setBeanClassLoader:" + classLoader.getClass());
}
public String doSth() {
System.out.println("serviceA doSth");
// throw new RuntimeException("an exception ");
return "hello";
}
}
改造BootConfig.java如下:
package com.test;
import com.test.service.ServiceA;
import org.springframework.beans.BeansException;
import org.springframework.context.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.metrics.ApplicationStartup;
/**
* @author felix
*/
@Configuration
@ComponentScan(basePackages = "com.test")
@EnableAspectJAutoProxy
public class BootConfig implements ApplicationStartupAware, ApplicationContextAware, ApplicationEventPublisherAware {
@Bean(initMethod = "init", destroyMethod = "destroy")
public ServiceA getServiceA() {
return new ServiceA();
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("setApplicationContext: " + applicationContext.getClass());
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("setApplicationEventPublisher: " + applicationEventPublisher);
}
public void setApplicationStartup(ApplicationStartup applicationStartup) {
System.out.println("setApplicationStartup" + applicationStartup);
}
}
启动测试类,结果如下:
setApplicationEventPublisher: org.springframework.context.annotation.AnnotationConfigApplicationContext@8807e25, started on Thu Sep 09 10:41:43 CST 2021
setApplicationStartuporg.springframework.core.metrics.DefaultApplicationStartup@77fbd92c
setApplicationContext: class org.springframework.context.annotation.AnnotationConfigApplicationContext
constructor
setBeanName:getServiceA
setBeanClassLoader:class sun.misc.Launcher$AppClassLoader
setBeanFactory:class org.springframework.beans.factory.support.DefaultListableBeanFactory
post construct
init
serviceA doSth
preDestroy
destroy
可以看到:
- 1.ApplicationEventPublisherAware生效,通过实现该接口,我们能在setApplicationEventPublisher方法拿到applicationEventPublisher,这个对象是用来向容器发布一些事件的
- 2.ApplicationStartupAware生效
- 3.ApplicationContextAware生效,这一步说明ApplicationContext已经创建了,我们可以拿到这个实例
- 4.执行了ServiceA的构造方法,说明这一步已经在实例化bean了
- 5.setBeanName bean处理,生成好了bean的名称
- 6.setBeanClassLoader bean处理,生成了bean的ClassLoader
- 7.setBeanFactory bean处理,设置BeanFactory
- 8.bean构造函数后置方法,容器对bean的赋能差不多了,该干点自己想干的事了
- 9.bean initMethod配置的初始化方法
- 10.bean业务代码
- 11.bean preDestroy
- 12.destroy