SpringBoot注解驱动
SpringBoot的事件监听
事件监听三大步。首先创建一个事件,然后创建一个监听器,再创建一个事件发布类。
事件的监听是在bean创建完成之后执行的,refresh()的最后一步执行:
事件类:事件类要继承ApplicationEvent这个抽象类,抽象类可以通过匿名内部类实现(如果没有抽象方法则大括号可以为空)
package com.hxh.event;
import org.springframework.context.ApplicationEvent;
import javax.validation.constraints.NotNull;
/**
* @author Hanxiaohan
* @date 2021/03/19 15:32
* @since 1.0
* <p>Copyright: Copyright (c) 2021</p>
*/
public class SelfEvent extends ApplicationEvent {
/**
* Create a new {@code ApplicationEvent}.
*
* @param source the object on which the event initially occurred or with
* which the event is associated (never {@code null})
*/
private static final long serialVersionUID = 1L;
private String message;
public SelfEvent(@NotNull Object source, String message) {
super(source);
this.message=message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
创建监听类:监听类继承ApplicationListener,泛型指定固定类型。
默认的Object source只有getSource()方法。可以添加其他属性(比如message)。
/**
* @author Hanxiaohan
* @date 2021/03/19 15:46
* @since 1.0
* <p>Copyright: Copyright (c) 2021</p>
*/
@Component
public class SignalListener implements ApplicationListener<SelfEvent> {
@Override
public void onApplicationEvent(SelfEvent event) {
System.out.println("test##### " + event.getMessage());
}
}
发布事件:事件的发布需要调用容器ApplicationContext,通过其publishEvent(),参数可以是ApplicationEvent或者自己设定的其他Event类。
/**
* @author Hanxiaohan
* @date 2021/03/19 15:50
* @since 1.0
* <p>Copyright: Copyright (c) 2021</p>
*/
@Component
public class EventPublisher {
@Resource
private Ginger ginger;
@Autowired
ApplicationContext applicationContext;
public void publish(String message){
applicationContext.publishEvent(new SelfEvent(ginger,ginger.toString()+ message));
}
}
本示例使用了一个普通bean作为source
@Component
public class Ginger {
@Value("China")
private String local;
@Value("3.14159")
private Double price;
@Override
public String toString() {
return "Ginger{" +
"local='" + local + '\'' +
", price=" + price +
'}';
}
public String getLocal() {
return local;
}
public void setLocal(String local) {
this.local = local;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
测试调用:
@SpringBootTest
class ExtendsApplicationTests03 {
@Autowired
private EventPublisher eventPublisher;
@Test
void contextLoads() {
eventPublisher.publish("卖生姜啦,预防脱发很有效!");
}
}
运行结果:
test##### Ginger{local='China', price=3.14159}卖生姜啦,预防脱发很有效!
ps:上面的监听使用了自己创建的SelfEvent event类型,如果使用ApplicationEvent,会把系统的事件也监听出来。
使用注解监听事件:@EventListener,可以添加多个class
但是监听方法只能有一个参数。
@Component
public class WoFe {
@EventListener({ApplicationEvent.class})
public void listten(ApplicationEvent event){
if(event.getSource().getClass() == Ginger.class){
System.out.println("注解实现::: " + ((SelfEvent)event).getMessage());
}
else{
System.out.println("注解实现::: 而我在等你"+event.getSource());
}
}
。。。
注解实现::: 而我在等你[DefaultTestContext@2e3967ea testClass = ExtendsApplicationTests03,
注解实现::: Ginger{local='China', price=3.14159}卖生姜啦,预防脱发很有效!
注解实现::: 而我在等你[DefaultTestContext@2e3967ea testClass = ExtendsApplicationTests03,
。。。
关于Spring *PostProcessor的总结
/**
* bean的生命周期:
* bean存在注册信息(ImportBeanDefinitionRegistrar)-->被加载到beanfactory-->被创建实例
* -->属性赋值(populate)-(BeanPostProcessor,*Aware)->初始化-->销毁
*
* beanfactory历程:
* spring首先创建beanfactory,然后标准初始化beanfactory。。
* 然后执行BeanFactoryPostProcessor(包含两个接口)
*
* BeanFactoryPostProcessor及其子接口
* BeanDefinitionRegistryPostProcessor
* 根据实现PriorityOrder接口执行子接口先。
* 再然后执行“注册BeanPostProcessor”。
*
* ApplicationContextAware:属性赋值之后,初始化之前
* BeanPostProcessor:在属性赋值之后,初始化之前
* BeanNameAware:同上,可修改beanname;
* BeanFactoryAware:在属性赋值之后,初始化之前
*
* BeanPostProcessor:Bean后置处理器,在bean对象初始化前后进行拦截工作。
* 1,BeanFactoryPostProcessor
* 在beanfactory标准初始化之后调用:所有的bean的定义已经加载到beanFactory但是还没有被
* 创建实例。可覆盖属性赋值。
*
* 2,BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
* postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
* 在所以bean定义信息将要被加载,bean实例还未被创建的时候执行。
*/
测试BeanDefinitionRegistryPostProcessor:
/**
* registries that hold bean definitions
*
* BeanDefinitionRegistry 为bean定义的存储中心;以后BeanFactory就是
* 按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例。
*
*/
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount()+"!");
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class);
registry.registerBeanDefinition("mmp",rootBeanDefinition);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Student.class).getBeanDefinition();
registry.registerBeanDefinition("mmlgb",beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount()+"!");
}
}
测试BeanFactoryPostProcessor
一个函数式接口,使用lambda表达式。
@Configuration
@Import({MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
@Bean
public BeanFactoryPostProcessor beanFactoryPostProcessor1(){
return ele -> {
int beanDefinitionCount = ele.getBeanDefinitionCount();
String[] beanDefinitionNames = ele.getBeanDefinitionNames();
System.out.println("当前beanfactory中有"+beanDefinitionCount+"个bean!");
System.out.println(Arrays.asList(beanDefinitionNames));
};
}
}
测试ImportBeanDefinitionRegistrar,使用注解导入bean:@Import({MyImportBeanDefinitionRegistrar.class})
/**
* AnnotationMetadata: 当前类的注解信息
* BeanDefinitionRegistry:
* 注册类把所有需要添加到容器中的bean
* 调用registerBeanDefinitions手工注册进来
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
boolean mmb1 = registry.containsBeanDefinition("mmp");
boolean mmb2 = registry.containsBeanDefinition("mmlgb");
if(!mmb1 && !mmb2){
registry.registerBeanDefinition("goodbye", new RootBeanDefinition(Student.class));
System.out.println("注册进去goodbye");
}
}
}
测试BeanPostProcessor
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
if(o.getClass()==Lp.class){
System.out.println("3+6= 9");
}
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
if(s.equals("mmp")){
System.out.println("-3-6= -9");
}
return o;
}
}
几种*Aware反注入的实现
运行在bean实例化之后,初始化方法执行之前: |
/**
* @author Hanxiaohan
* @date 2021/03/16 10:04
* @since 1.0.1
* <p>Copyright: Copyright (c) 2021</p>
*/
@Component
public class NiuPi implements ApplicationContextAware , BeanNameAware, EmbeddedValueResolverAware, EnvironmentAware {
@Autowired
private Lp lb;
private StringValueResolver stringValueResolver;
@Override
public String toString() {
return "NiuPi{" +
"lb=" + lb +
'}';
}
private ApplicationContext application;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.application=applicationContext;
for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
@Override
public void setBeanName(String name) {
System.out.println(name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
this.stringValueResolver=stringValueResolver;
System.out.println(stringValueResolver.resolveStringValue("#{7.8*75*0.35}"));
}
@Override
public void setEnvironment(Environment environment) {
System.out.println(environment.getProperty("os.name"));
}
}
@Primary与@Scope 注解含义
@Configuration
public class Cai {
// @Scope("prototype")
@Primary
@Bean("mmp")
public Lv lv1(){
Lv lv = new Lv();
lv.setAge(100);
return lv;
}
}