文章目录

  • SpringBoot注解驱动
    • SpringBoot的事件监听
    • 关于Spring *PostProcessor的总结
    • 几种*Aware反注入的实现

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> {@Overridepublic 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 {@Resourceprivate Ginger ginger;@AutowiredApplicationContext 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;@Overridepublic 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 {@Autowiredprivate EventPublisher eventPublisher;@Testvoid 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 {@Overridepublic 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);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount()+"!");}
}

测试BeanFactoryPostProcessor
一个函数式接口,使用lambda表达式。

@Configuration
@Import({MyImportBeanDefinitionRegistrar.class})
public class MainConfig {@Beanpublic 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 {@Overridepublic 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 {@Overridepublic Object postProcessBeforeInitialization(Object o, String s) throws BeansException {if(o.getClass()==Lp.class){System.out.println("3+6= 9");}return o;}@Overridepublic 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 {@Autowiredprivate Lp lb;private StringValueResolver stringValueResolver;@Overridepublic String toString() {return "NiuPi{" +"lb=" + lb +'}';}private ApplicationContext application;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.application=applicationContext;for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}@Overridepublic void setBeanName(String name) {System.out.println(name);}@Overridepublic void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {this.stringValueResolver=stringValueResolver;System.out.println(stringValueResolver.resolveStringValue("#{7.8*75*0.35}"));}@Overridepublic 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;}}

Spring注解驱动相关推荐

  1. 0、Spring 注解驱动开发

    0.Spring注解驱动开发 0.1 简介 <Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作 ...

  2. Spring注解驱动开发第26讲——总有人让我给他讲讲@EnableAspectJAutoProxy注解

    @EnableAspectJAutoProxy注解 在配置类上添加@EnableAspectJAutoProxy注解,便能够开启注解版的AOP功能.也就是说,如果要使注解版的AOP功能起作用的话,那么 ...

  3. Spring注解驱动开发学习总结8:自动装配注解@Autowire、@Resource、@Inject

    Spring注解驱动开发学习总结8:自动装配注解@Autowire.@Resource.@Inject 1.自动装配@Autowire.@Resource.@Inject 1.1 构建bookDao ...

  4. 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解

    写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...

  5. SPRING注解驱动开发-雷神课程超详细笔记

    SPRING注解驱动开发-雷神课程超详细笔记 时间:2021-03-21 2022-04-06更新:最近翻起一年多前写的笔记复习,还是收获颇多,很多当时无法理解的知识现在慢慢能理解了,可能是工作一年的 ...

  6. spring注解驱动开发-5 Spring AOP实现

    Spring AOP实现 前言 AOP案例实现 1.编写目标类 2.编写切面类 3.编写配置类 4.编写测试类 end... 前言 AOP为Aspect Oriented Programming的缩写 ...

  7. spring注解驱动开发-10 Servlet3.0

    Spring AOP实现 前言 servlet3.0简介 ServletContainerInitializer shared libraries(共享库) / runtimes pluggabili ...

  8. spring注解驱动开发-8 Spring 扩展原理

    Spring 扩展原理 前言 BeanFactoryPostProcessor 测试实例编写 ExtConfig MyBeanFactoryPostProcessor ExtTest 源码分析 Bea ...

  9. spring注解驱动开发-4 Spring 自动装配

    Spring 自动装配 前言 Spring 自动装配的几种方式 1.@Autowired @Qualifier("组件id") @Primary 2.@Resource方式 3.@ ...

  10. spring注解驱动开发-7 Spring声明式事务

    Spring 声明式事务 前言 @EnableTransactionManagement AutoProxyRegistrar InfrastructureAdvisorAutoProxyCreato ...

最新文章

  1. gcc 编译 java,编译lineage,gcc的版本问题
  2. MAC下《暗黑世界》客户端版本编译说明!!
  3. cordova报错:Error: Failed to find ‘ANDROID_HOME‘ environment variable. Try setting setting it manually
  4. 兰州大学第一届 飞马杯 ★★快乐苹果树★★ 树链剖分 + 懒标记 + 树状数组
  5. gcc: weak_alias如何使用
  6. 微信各地服务器如何同步,彻底搞清楚并实现多端同步登录
  7. 从武汉模式走向中国模式,打造人工智能产业发展的“中国样板”
  8. CentOS7设置中文字符集
  9. 数据库提示日志文件不可用
  10. 16bit随机数生成matlab,关于matlab生成随机数
  11. 数据库系统概论(各章知识点总结)
  12. 【机器学习】 - 决策树(西瓜数据集)
  13. Google Earth Engine——使用climata和Python从USGS获取流数据
  14. 【arc075f】AtCoder Regular Contest 075 F - Mirrored
  15. 输入在第一行中给出一个正整数n(1)。第二行输入n个整数,用空格分开。在一行中输出最大值及最大值的最小下标,中间用一个空格分开。
  16. 【PM模块】预防性维护
  17. oracle中private同义词和public同义词
  18. MT940银行对账单怎么解析呢
  19. 原生TabLayout使用
  20. 被资本和冬奥吹热的服务机器人,不止是昙花一现

热门文章

  1. 爱快中的虚拟机不能获取IPV4地址
  2. mysql 手机号省份_根据手机号 判断省份和运营商
  3. CPU、处理器、内存、外存、寄存器、缓存的区别
  4. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛
  5. 1到100的和(C)
  6. grant之后要跟着flush privileges吗?
  7. N01web网页设计实例作大作业(div+css) ——中国茶文化(6页) 茶文化网页制作作业_中国化(网页设计...
  8. 丢番图生平编程java_丢番图
  9. Eclipse jdt 格式化java代码
  10. Java jdt 编辑_使用JDT转java代码为AST