Spring注解驱动
文章目录
- 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注解驱动相关推荐
- 0、Spring 注解驱动开发
0.Spring注解驱动开发 0.1 简介 <Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作 ...
- Spring注解驱动开发第26讲——总有人让我给他讲讲@EnableAspectJAutoProxy注解
@EnableAspectJAutoProxy注解 在配置类上添加@EnableAspectJAutoProxy注解,便能够开启注解版的AOP功能.也就是说,如果要使注解版的AOP功能起作用的话,那么 ...
- Spring注解驱动开发学习总结8:自动装配注解@Autowire、@Resource、@Inject
Spring注解驱动开发学习总结8:自动装配注解@Autowire.@Resource.@Inject 1.自动装配@Autowire.@Resource.@Inject 1.1 构建bookDao ...
- 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...
- SPRING注解驱动开发-雷神课程超详细笔记
SPRING注解驱动开发-雷神课程超详细笔记 时间:2021-03-21 2022-04-06更新:最近翻起一年多前写的笔记复习,还是收获颇多,很多当时无法理解的知识现在慢慢能理解了,可能是工作一年的 ...
- spring注解驱动开发-5 Spring AOP实现
Spring AOP实现 前言 AOP案例实现 1.编写目标类 2.编写切面类 3.编写配置类 4.编写测试类 end... 前言 AOP为Aspect Oriented Programming的缩写 ...
- spring注解驱动开发-10 Servlet3.0
Spring AOP实现 前言 servlet3.0简介 ServletContainerInitializer shared libraries(共享库) / runtimes pluggabili ...
- spring注解驱动开发-8 Spring 扩展原理
Spring 扩展原理 前言 BeanFactoryPostProcessor 测试实例编写 ExtConfig MyBeanFactoryPostProcessor ExtTest 源码分析 Bea ...
- spring注解驱动开发-4 Spring 自动装配
Spring 自动装配 前言 Spring 自动装配的几种方式 1.@Autowired @Qualifier("组件id") @Primary 2.@Resource方式 3.@ ...
- spring注解驱动开发-7 Spring声明式事务
Spring 声明式事务 前言 @EnableTransactionManagement AutoProxyRegistrar InfrastructureAdvisorAutoProxyCreato ...
最新文章
- gcc 编译 java,编译lineage,gcc的版本问题
- MAC下《暗黑世界》客户端版本编译说明!!
- cordova报错:Error: Failed to find ‘ANDROID_HOME‘ environment variable. Try setting setting it manually
- 兰州大学第一届 飞马杯 ★★快乐苹果树★★ 树链剖分 + 懒标记 + 树状数组
- gcc: weak_alias如何使用
- 微信各地服务器如何同步,彻底搞清楚并实现多端同步登录
- 从武汉模式走向中国模式,打造人工智能产业发展的“中国样板”
- CentOS7设置中文字符集
- 数据库提示日志文件不可用
- 16bit随机数生成matlab,关于matlab生成随机数
- 数据库系统概论(各章知识点总结)
- 【机器学习】 - 决策树(西瓜数据集)
- Google Earth Engine——使用climata和Python从USGS获取流数据
- 【arc075f】AtCoder Regular Contest 075 F - Mirrored
- 输入在第一行中给出一个正整数n(1)。第二行输入n个整数,用空格分开。在一行中输出最大值及最大值的最小下标,中间用一个空格分开。
- 【PM模块】预防性维护
- oracle中private同义词和public同义词
- MT940银行对账单怎么解析呢
- 原生TabLayout使用
- 被资本和冬奥吹热的服务机器人,不止是昙花一现
热门文章
- 爱快中的虚拟机不能获取IPV4地址
- mysql 手机号省份_根据手机号 判断省份和运营商
- CPU、处理器、内存、外存、寄存器、缓存的区别
- 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛
- 1到100的和(C)
- grant之后要跟着flush privileges吗?
- N01web网页设计实例作大作业(div+css) ——中国茶文化(6页) 茶文化网页制作作业_中国化(网页设计...
- 丢番图生平编程java_丢番图
- Eclipse jdt 格式化java代码
- Java jdt 编辑_使用JDT转java代码为AST