- SpringApplication
- spring的注解编程模型
- Spring 模式注解:Stereotype Annotations
- Spring Boot 应用的引导
- Spring Boot 事件
- Spring的事件机制案例
- bean的生命周期
springboot启动类就是SpringApplication。
SpringApplication
简单实例
为了使用springboot,springboot快速构建,下载代码;
拷贝相关的依赖
创建启动类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
这里有两个关键@SpringBootApplication
注解类、SpringApplication启动类;
@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
@ComponentScan
:Spring Framework 3.1引入
@EnableAutoConfiguration
:
激活自动装配 @Enable -> @Enable 开头的
- @EnableWebMvc
- @EnableTransactionManagement
- @EnableAspectJAutoProxy
- @EnableAsync
@SpringBootConfiguration : 等价于 @Configuration -> Configuration Class 注解
@Component -> @ComponentScan
处理类 -> ConfigurationClassParser
扫描类 ->
- ClassPathBeanDefinitionScanner
- ClassPathScanningCandidateComponentProvider
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ... }
spring的注解编程模型
-
@Component
- @Service
@Component public @interface Service { ... }
-
@Repository
@Component public @interface Repository { ... }
-
@Controller
@Component public @interface Controller { ... }
-
@Configuration
@Component public @interface Configuration { ... }
Spring 模式注解:Stereotype Annotations
Spring 注解驱动示例
注解驱动上下文 AnnotationConfigApplicationContext , Spring Framework 3.0 开始引入的
@Configuration
public class SpringAnnotationDemo {
public static void main(String[] args) {
// XML 配置文件驱动 ClassPathXmlApplicationContext
// Annotation 驱动
// 找 BeanDefinition
// @Bean @Configuration
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册一个 Configuration Class = SpringAnnotationDemo
context.scan("com.gupao.microservicesproject");
// 上下文启动
context.refresh();
System.out.println(context.getBean(SpringAnnotationDemo.class));
}
}
@SpringBootApplication
标注当前一些功能
-
@SpringBootApplication
-
@SpringBootConfiguration
-
@Configuration
- @Component
-
-
Spring Boot 应用的引导
基本写法
SpringApplication
SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);
Map<String,Object> properties = new LinkedHashMap<>();
properties.put("server.port",0);
springApplication.setDefaultProperties(properties);
springApplication.run(args);
SpringApplicationBuilder
new SpringApplicationBuilder(MicroservicesProjectApplication.class) // Fluent API
// 单元测试是 PORT = RANDOM
.properties("server.port=0") // 随机向 OS 要可用端口
.run(args);
Spring Boot 引导示例
@SpringBootApplication
public class MicroservicesProjectApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);
Map<String,Object> properties = new LinkedHashMap<>();
properties.put("server.port",0);
springApplication.setDefaultProperties(properties);
ConfigurableApplicationContext context = springApplication.run(args);
// 有异常?
System.out.println(context.getBean(MicroservicesProjectApplication.class));
}
}
调整示例为 非 Web 程序
@SpringBootApplication
public class MicroservicesProjectApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);
Map<String, Object> properties = new LinkedHashMap<>();
properties.put("server.port", 0);
springApplication.setDefaultProperties(properties);
// 设置为 非 web 应用
springApplication.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = springApplication.run(args);
// 有异常?
System.out.println(context.getBean(MicroservicesProjectApplication.class));
// 输出当前 Spring Boot 应用的 ApplicationContext 的类名
System.out.println("当前 Spring 应用上下文的类:" + context.getClass().getName());
}
}
Spring Boot 事件
Spring 事件
Spring 内部发送事件
-
ContextRefreshedEvent
-
ApplicationContextEvent
- ApplicationEvent
-
refresh() -> finishRefresh() -> publishEvent(new ContextRefreshedEvent(this));
- ContextClosedEvent
- ApplicationContextEvent
- ApplicationEvent
- ApplicationContextEvent
close() -> doClose() -> publishEvent(new ContextClosedEvent(this));
自定义事件
PayloadApplicationEvent
Spring 事件 都是 ApplicationEvent 类型
发送 Spring 事件通过 ApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)
Spring 事件的类型 ApplicationEvent
Spring 事件监听器 ApplicationListener
Spring 事件广播器 ApplicationEventMulticaster
- 实现类:SimpleApplicationEventMulticaster
Spring 事件理解为消息
ApplicationEvent 相当于消息内容
ApplicationListener 相当于消息消费者、订阅者
ApplicationEventMulticaster 相当于消息生产者、发布者
Spring Boot 事件监听示例
@EnableAutoConfiguration
public class SpringBootEventDemo {
public static void main(String[] args) {
new SpringApplicationBuilder(SpringBootEventDemo.class)
.listeners(event -> { // 增加监听器
System.err.println("监听到事件 : " + event.getClass().getSimpleName());
})
.run(args)
.close();
; // 运行
}
}
- ApplicationStartingEvent(1)
- ApplicationEnvironmentPreparedEvent(2)
- ApplicationPreparedEvent(3)
- ContextRefreshedEvent
- ServletWebServerInitializedEvent
- ApplicationStartedEvent(4)
- ApplicationReadyEvent(5)
- ContextClosedEvent
- ApplicationFailedEvent (特殊情况)(6)
Spring Boot 事件监听器
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
ConfigFileApplicationListener 监听 ApplicationEnvironmentPreparedEvent 事件
从而加载 application.properties 或者 application.yml 文件
Spring Boot 很多组件依赖于 Spring Boot 事件监听器实现,本质是 Spring Framework 事件/监听机制
SpringApplication 利用
- Spring 应用上下文(ApplicationContext)生命周期控制 注解驱动 Bean
- Spring 事件/监听(ApplicationEventMulticaster)机制加载或者初始化组件
框架底层的事件是单线程么?业务实现是否可以使用事件去实现?如果使用事件实现会不会是不是会有性能问题?
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
...
}
Spring的事件机制案例
事件发布者
//需要实现ApplicationEventPublisherAware这个Aware接口,广播事件需要利用applicationEventPublisher
@Component
public class SaySomethingPublisher implements ApplicationEventPublisherAware{
private ApplicationEventPublisher applicationEventPublisher;
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void saySomething(String msg){
applicationEventPublisher.publishEvent(msg);
}
}
事件监听者
//事件监听者需要实现ApplicationListener接口
@Component
public class ListenerA implements ApplicationListener<PayloadApplicationEvent<String>> {
// 由于监听的是String类型的事件会被封装成PayloadApplicationEvent,所以此处类型是PayloadApplicationEvent
public void onApplicationEvent(PayloadApplicationEvent event) {
// getSource返回真实的事件
Object msg = event.getSource();
System.out.println("ListenerA receive:" + msg);
}
}
可以测试
public class SpringEventListenerDemo {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
// 添加自义定监听器
context.addApplicationListener(new ClosedListener());
context.addApplicationListener(new RefreshedListener());
context.addApplicationListener(new MyEventListener());
// 启动 Spring 应用上下文
context.refresh();
context.publishEvent("HelloWorld"); // 发布一个 HelloWorld 内容的事件
// 一个是 MyEvent
context.publishEvent(new MyEvent("HelloWorld 2018"));
// 一个是 ContextClosedEvent
// 关闭应用上下文
context.close();
}
private static class RefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("上下文启动:" + event);
}
}
private static class ClosedListener implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
System.out.println("关闭上下文:" + event);
}
}
private static class MyEventListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("监听到:" + event.getSource());
}
}
private static class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
}
bean的生命周期
Bean 生命周期
实例化 -> Bean Class -> Bean Object
初始化前 -> Bean before/pre init()
- org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
初始化 -> init()
- org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
初始化后
- org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization()
销毁
- org.springframework.beans.factory.DisposableBean#destroy()