文章目录
- 前言
- 一、Springboot 接口:ApplicationRunner 与 CommandLineRunner
- 二、PostConstructor 和 InitializingBean
- 三、Spring的ApplicationListener
- 总结
前言
采用springboot 搭建项目时,有时候可能需要在项目启动后自动加载一些数据 ,那么我们可以采取一下几种方式来帮我们实现这个功能:
Springboot: ApplicationRunner 与 CommandLineRunner 接口
Spring容器初始化时 实现InitializingBean接口和@PostConstruct方法
Spring的ApplicationListener
提示:以下是本篇文章正文内容,下面案例可供参考
一、Springboot 接口:ApplicationRunner 与 CommandLineRunner
我们从springboot启动开始,一步步调用来查看相关的代码实现
SpringApplication.run(MyApplication.class, args) ->
SpringApplication run(Object source, String... args) ->
SpringApplication run(Object[] sources, String[] args) ->
SpringApplication run(String... args) ->
SpringApplication afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) ->
SpringApplication callRunners(ApplicationContext context, ApplicationArguments args)
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList();
//获取spring容器下所有实现ApplicationRunner接口的类加入runners容器中
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
//获取spring容器下所有实现CommandLineRunner接口的类加入runners容器中
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
Iterator var4 = (new LinkedHashSet(runners)).iterator();
while(var4.hasNext()) {
Object runner = var4.next();
if (runner instanceof ApplicationRunner) {
//ApplicationRunner接口调用
this.callRunner((ApplicationRunner)runner, args);
}
if (runner instanceof CommandLineRunner) {
//CommandLineRunner接口调用
this.callRunner((CommandLineRunner)runner, args);
}
}
}
好啦,调用过程已经清楚了,那我们写个简单例子来测试下
@Component
public class ApplicationRunnerTest implements ApplicationRunner {
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
System.out.println("ApplicationRunnerTest ----- only for test");
}
}
二、PostConstructor 和 InitializingBean
代码如下(示例):
在bean初始化的时候,如果bean实现了 InitializingBean 接口,那么在初始化之后会调用afterPropertiesSet().同样我们也从springboot启动流程来看。
SpringApplication.run(MyApplication.class, args) ->
SpringApplication run(Object source, String... args) ->
SpringApplication run(Object[] sources, String[] args) ->
SpringApplication run(String... args) ->
SpringApplication refreshContext(ConfigurableApplicationContext context) ->
SpringApplication refresh(ApplicationContext applicationContext) ->
EmbeddedWebApplicationContext refresh() ->
AbstractApplicationContext refresh() ->
AbstractApplicationContext finishBeanFactoryInitialization() ->
DefaultListableBeanFactory preInstantiateSingletons() ->
AbstractBeanFactory getBean(String name) ->
AbstractBeanFactory doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
DefaultSingletonBeanRegistry getSingleton(String beanName, ObjectFactory<?> singletonFactory) ->
AbstractAutowireCapableBeanFactory createBean(String beanName, RootBeanDefinition mbd, Object[] args) ->
AbstractAutowireCapableBeanFactory doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) ->
AbstractAutowireCapableBeanFactory initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
//经过坎坷的调用过程,终于来到主题了
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
return null;
}
}, this.getAccessControlContext());
} else {
//调用实现Aware接口的方法, 这不是这次的重点忽略
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//BeforeInitialization 调用beanPostProcessor 的方法
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//调用init方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
//AfterInitialization 调用beanPostProcessor 的方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
先看看applyBeanPostProcessorsBeforeInitialization的方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
//获取所有实现BeanPostProcessor接口的类
Iterator var4 = this.getBeanPostProcessors().iterator();
do {
if (!var4.hasNext()) {
return result;
}
BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
//调用postProcessBeforeInitialization方法
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
} while(result != null);
return result;
}
这里主要来看CommonAnnotationBeanPostProcessor
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
//CommonAnnotationBeanPostProcessor是继承自InitDestroyAnnotationBeanPostProcessor
public CommonAnnotationBeanPostProcessor() {
this.setOrder(2147483644);
//构造函数:这里将AnnotationType设置为PostConstructor类;
this.setInitAnnotationType(PostConstruct.class);
this.setDestroyAnnotationType(PreDestroy.class);
this.ignoreResourceType("javax.xml.ws.WebServiceContext");
}
由于CommonAnnotationBeanPostProcessor没有实现postProcessBeforeInitialization,那么我们得查看它的父类:InitDestroyAnnotationBeanPostProcessor
InitDestroyAnnotationBeanPostProcessor postProcessBeforeInitialization(Object bean, String beanName) ->
InitDestroyAnnotationBeanPostProcessor findLifecycleMetadata(Class<?> clazz) ->
InitDestroyAnnotationBeanPostProcessor buildLifecycleMetadata(final Class<?> clazz)
private InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
final boolean debug = this.logger.isDebugEnabled();
LinkedList<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> initMethods = new LinkedList();
LinkedList<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> destroyMethods = new LinkedList();
Class targetClass = clazz;
do {
final LinkedList<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> currInitMethods = new LinkedList();
final LinkedList<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> currDestroyMethods = new LinkedList();
ReflectionUtils.doWithLocalMethods(targetClass, new MethodCallback() {
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
//判断initAnnotationType是否为空,之前CommonAnnotationBeanPostProcessor的构造函数中已经将initAnnotationType设置为PostConstructor。也就是判断方法上是否有PostConstructor注解
if (InitDestroyAnnotationBeanPostProcessor.this.initAnnotationType != null && method.getAnnotation(InitDestroyAnnotationBeanPostProcessor.this.initAnnotationType) != null) {
InitDestroyAnnotationBeanPostProcessor.LifecycleElement element = new InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method);
//方法上有PostConstructor注解则就将方法添加进LifecycleMetadata
currInitMethods.add(element);
if (debug) {
InitDestroyAnnotationBeanPostProcessor.this.logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (InitDestroyAnnotationBeanPostProcessor.this.destroyAnnotationType != null && method.getAnnotation(InitDestroyAnnotationBeanPostProcessor.this.destroyAnnotationType) != null) {
currDestroyMethods.add(new InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method));
if (debug) {
InitDestroyAnnotationBeanPostProcessor.this.logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
} while(targetClass != null && targetClass != Object.class);
return new InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata(clazz, initMethods, destroyMethods);
}
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> initMethodsToIterate = this.checkedInitMethods != null ? this.checkedInitMethods : this.initMethods;
if (!((Collection)initMethodsToIterate).isEmpty()) {
boolean debug = InitDestroyAnnotationBeanPostProcessor.this.logger.isDebugEnabled();
InitDestroyAnnotationBeanPostProcessor.LifecycleElement element;
//获取到注解上有PostConstructor的方法,在这里invoke(反射调用)
for(Iterator var5 = ((Collection)initMethodsToIterate).iterator(); var5.hasNext(); element.invoke(target)) {
element = (InitDestroyAnnotationBeanPostProcessor.LifecycleElement)var5.next();
if (debug) {
InitDestroyAnnotationBeanPostProcessor.this.logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
}
}
}
好啦,调用过程已经清楚了,那我们写个简单例子来测试下
@Component
public class PostConstructorTest {
@PostConstruct
public void postConstrctorTest(){
System.out.println("postConstrctorTest ----- only for test");
}
}
接下来我们看看InitializingBean的调用过程
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean)bean).afterPropertiesSet();
return null;
}
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
//InitializingBean调用,是不是很简单,直接就调用afterPropertiesSet,没有任何反射过程
((InitializingBean)bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
三、Spring的ApplicationListener
在spring 容器中,实际上有许多事件例如ContextStartedEvent, ContextStoppedEvent, ContextRefreshedEvent,ContextClosedEvent。甚至我们自己也可以自定义事件,这里我们只对ContextRefreshedEvent进行分析。
首先当然是查看监听器获取的过程。
SpringApplication.run(MyApplication.class, args) ->
SpringApplication run(Object source, String... args) ->
SpringApplication run(Object[] sources, String[] args) ->
SpringApplication run(String... args) ->
SpringApplication refreshContext(ConfigurableApplicationContext context) ->
SpringApplication refresh(ApplicationContext applicationContext) ->
EmbeddedWebApplicationContext refresh() ->
AbstractApplicationContext refresh() ->
AbstractApplicationContext registerListeners()
protected void registerListeners() {
Iterator var1 = this.getApplicationListeners().iterator();
while(var1.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var1.next();
this.getApplicationEventMulticaster().addApplicationListener(listener);
}
//从容器中获取所有实现ApplicationListener接口的类
String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
String[] var7 = listenerBeanNames;
int var3 = listenerBeanNames.length;
for(int var4 = 0; var4 < var3; ++var4) {
String listenerBeanName = var7[var4];
//将所有ApplicationListener加入 AbstractApplicationEventMulticaster 类中容器,以便以后的调用
this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
Iterator var9 = earlyEventsToProcess.iterator();
while(var9.hasNext()) {
ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
接下来查看spring如何发布ContextRefresh事件
SpringApplication.run(MyApplication.class, args) ->
SpringApplication run(Object source, String... args) ->
SpringApplication run(Object[] sources, String[] args) ->
SpringApplication run(String... args) ->
SpringApplication refreshContext(ConfigurableApplicationContext context) ->
SpringApplication refresh(ApplicationContext applicationContext) ->
EmbeddedWebApplicationContext refresh() ->
AbstractApplicationContext refresh() ->
AbstractApplicationContext finishRefresh() ->
AbstractApplicationContext publishEvent(ApplicationEvent event) ->
AbstractApplicationContext publishEvent(Object event, ResolvableType eventType) ->
SimpleApplicationEventMulticaster multicastEvent(final ApplicationEvent event, ResolvableType eventType) ->
SimpleApplicationEventMulticaster invokeListener(ApplicationListener listener, ApplicationEvent event)
protected void finishRefresh() {
this.initLifecycleProcessor();
this.getLifecycleProcessor().onRefresh();
//这里传入的事件是ContextRefreshedEvent
this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
LiveBeansView.registerApplicationContext(this);
}
//终于来到了最终方法调用, listener 在之前已经注入到AbstractApplicationEventMulticaster类中容器
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = this.getErrorHandler();
if (errorHandler != null) {
try {
listener.onApplicationEvent(event);
} catch (Throwable var6) {
errorHandler.handleError(var6);
}
} else {
try {
//调用onApplicationEvent方法
listener.onApplicationEvent(event);
} catch (ClassCastException var5) {
LogFactory.getLog(this.getClass()).debug("Non-matching event type for listener: " + listener, var5);
}
}
}
有两种方法可以创建监听者,一种是直接实现ApplicationListener的接口,一种是使用注解 @EventListener ,取其中一种来试试水。
@Component
public class ApplicationListenerTest {
@EventListener
public void onApplicationEvent(ContextRefreshedEvent event){
System.out.println("ApplicationListenerTest ----- only for test");
}
}
总结
最终我们测试出结果顺序如下
afterPropertiesSet ----- only for test
postConstrctorTest ----- only for test
ApplicationListenerTest ----- only for test
ApplicationRunnerTest ----- only for test
如此看来,springboot 的启动流程是不是也十分简单~~