示例1
项目结构
demo01 包结构:
src/main/java/demo01
├── Demo01Main.java
├── TestBean01.java
├── TestBean02.java
└── TestBean03.java
TestBean01.java
TestBean01 类内容:
package demo01;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class TestBean01 implements InitializingBean, ApplicationContextAware, ApplicationListener {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this.getClass().getCanonicalName() + " afterPropertiesSet");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(this.getClass().getCanonicalName() + " setApplicationContext");
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println(this.getClass().getCanonicalName() + " event: " + event.getClass().getCanonicalName());
}
}
TestBean02.java、TestBean03.java
TestBean02、TestBean03 内容和 TestBean01 相同。
Demo01Main.java
Demo01Main 类内容:
package demo01;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class Demo01Main {
@Test
public void test01() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Demo01Main.class);
System.out.println("finish");
}
@Test
public void test02() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Demo01Main.class);
ctx.start();
System.out.println("finish");
}
}
执行 test01 函数,结果为:
demo01.TestBean01 setApplicationContext
demo01.TestBean01 afterPropertiesSet
demo01.TestBean02 setApplicationContext
demo01.TestBean02 afterPropertiesSet
demo01.TestBean03 setApplicationContext
demo01.TestBean03 afterPropertiesSet
demo01.TestBean01 event: org.springframework.context.event.ContextRefreshedEvent
demo01.TestBean02 event: org.springframework.context.event.ContextRefreshedEvent
demo01.TestBean03 event: org.springframework.context.event.ContextRefreshedEvent
finish
执行 test02 函数,结果为:
demo01.TestBean01 setApplicationContext
demo01.TestBean01 afterPropertiesSet
demo01.TestBean02 setApplicationContext
demo01.TestBean02 afterPropertiesSet
demo01.TestBean03 setApplicationContext
demo01.TestBean03 afterPropertiesSet
demo01.TestBean01 event: org.springframework.context.event.ContextRefreshedEvent
demo01.TestBean02 event: org.springframework.context.event.ContextRefreshedEvent
demo01.TestBean03 event: org.springframework.context.event.ContextRefreshedEvent
demo01.TestBean01 event: org.springframework.context.event.ContextStartedEvent
demo01.TestBean02 event: org.springframework.context.event.ContextStartedEvent
demo01.TestBean03 event: org.springframework.context.event.ContextStartedEvent
finish
当 Spring 初始化完毕后,会发布 ContextRefreshedEvent 事件。
在初始化一个 bean 时,ApplicationContextAware 的 setApplicationContext 方法比 InitializingBean 的 afterPropertiesSet 方法优先执行。
调用 AnnotationConfigApplicationContext 的 start 方法时候,会发布 ContextStartedEvent 事件,用于通知 spring 已经启动好了。
示例2
项目结构
demo02 包结构如下:
src/main/java/demo02
├── Demo02Main.java
├── TestBean01.java
├── TestBean02.java
└── TestBean03.java
TestBean01.java
TestBean01 内容如下:
package demo02;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class TestBean01 implements InitializingBean, ApplicationContextAware, ApplicationListener {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this.getClass().getCanonicalName() + " afterPropertiesSet");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(this.getClass().getCanonicalName() + " setApplicationContext");
applicationContext.getBean(TestBean03.class); // 获取 TestBean03 bean
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println(this.getClass().getCanonicalName() + " event: " + event.getClass().getCanonicalName());
}
}
TestBean02.java
TestBean02 类内容如下:
package demo02;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class TestBean02 implements InitializingBean, ApplicationContextAware, ApplicationListener {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this.getClass().getCanonicalName() + " afterPropertiesSet");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(this.getClass().getCanonicalName() + " setApplicationContext");
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println(this.getClass().getCanonicalName() + " event: " + event.getClass().getCanonicalName());
}
}
TestBean03.java
TestBean03 和 TestBean02 内容相同。
Demo02Main.java
Demo02Main 类内容如下:
package demo02;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class Demo02Main {
@Test
public void test01() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Demo02Main.class);
System.out.println("finish");
}
}
执行 test01 ,结果为:
demo02.TestBean01 setApplicationContext
demo02.TestBean03 setApplicationContext
demo02.TestBean03 afterPropertiesSet
demo02.TestBean01 afterPropertiesSet
demo02.TestBean02 setApplicationContext
demo02.TestBean02 afterPropertiesSet
demo02.TestBean03 event: org.springframework.context.event.ContextRefreshedEvent
demo02.TestBean01 event: org.springframework.context.event.ContextRefreshedEvent
demo02.TestBean02 event: org.springframework.context.event.ContextRefreshedEvent
finish
在初始化 TestBean01 时,setApplicationContext 方法中尝试获取 TestBean03 的 bean,于是 TestBean03 打断了 TestBean01 初始化,等 TestBean03 初始化完毕后,TestBean01 继续初始化。然后 TestBean02 初始化。
从这里可以推论:spring 先扫描所有的要处理的类,记录下来,然后一个个初始化。