正确实现用spring扫描自定义的annotation
背景
在使用spring时,有时候有会有一些自定义annotation的需求,比如一些Listener的回调函数。
比如:
@Service
public class MyService {@MyListenerpublic void onMessage(Message msg){}
}
一开始的时候,我是在Spring的ContextRefreshedEvent
事件里,通过context.getBeansWithAnnotation(Component.class)
来获取到所有的bean,然后再检查method是否有@MyListener
的annotation。
后来发现这个方法有缺陷,当有一些spring bean的@Scope
设置为session/request时,创建bean会失败。
参考:
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes
在网上搜索了一些资料,发现不少人都是用context.getBeansWithAnnotation(Component.class)
,这样子来做的,但是这个方法并不对。
BeanPostProcessor接口
后来看了下spring jms里的@JmsListener
的实现,发现实现BeanPostProcessor
接口才是最合理的办法。
public interface BeanPostProcessor {/*** Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}* or a custom init-method). The bean will already be populated with property values.* The returned bean instance may be a wrapper around the original.* @param bean the new bean instance* @param beanName the name of the bean* @return the bean instance to use, either the original or a wrapped one;* if {@code null}, no subsequent BeanPostProcessors will be invoked* @throws org.springframework.beans.BeansException in case of errors* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet*/Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;/*** Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}* or a custom init-method). The bean will already be populated with property values.* The returned bean instance may be a wrapper around the original.* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean* instance and the objects created by the FactoryBean (as of Spring 2.0). The* post-processor can decide whether to apply to either the FactoryBean or created* objects or both through corresponding {@code bean instanceof FactoryBean} checks.* <p>This callback will also be invoked after a short-circuiting triggered by a* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,* in contrast to all other BeanPostProcessor callbacks.* @param bean the new bean instance* @param beanName the name of the bean* @return the bean instance to use, either the original or a wrapped one;* if {@code null}, no subsequent BeanPostProcessors will be invoked* @throws org.springframework.beans.BeansException in case of errors* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet* @see org.springframework.beans.factory.FactoryBean*/Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;}
所有的bean在创建完之后,都会回调postProcessAfterInitialization
函数,这时就可以确定bean是已经创建好的了。
所以扫描自定义的annotation的代码大概是这个样子的:
public class MyListenerProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());if (methods != null) {for (Method method : methods) {MyListener myListener = AnnotationUtils.findAnnotation(method, MyListener.class);// process}}return bean;}
}
SmartInitializingSingleton 接口
看spring jms的代码时,发现SmartInitializingSingleton 这个接口也比较有意思。
就是当所有的singleton的bean都初始化完了之后才会回调这个接口。不过要注意是 4.1 之后才出现的接口。
public interface SmartInitializingSingleton {/*** Invoked right at the end of the singleton pre-instantiation phase,* with a guarantee that all regular singleton beans have been created* already. {@link ListableBeanFactory#getBeansOfType} calls within* this method won't trigger accidental side effects during bootstrap.* <p><b>NOTE:</b> This callback won't be triggered for singleton beans* lazily initialized on demand after {@link BeanFactory} bootstrap,* and not for any other bean scope either. Carefully use it for beans* with the intended bootstrap semantics only.*/void afterSingletonsInstantiated();}
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/SmartInitializingSingleton.html
正确实现用spring扫描自定义的annotation相关推荐
- spring 扫描自定义注解
目录 一:定义自定义注解 二:使用自定义注解 3.1 定义使用注解的测试文件路径 3.2继承BeanPostProcessor增加spring扫描配置 四:测试 目录结构: 一:定义自定义注解 pac ...
- spring中自定义注解(annotation)与AOP中获取注解___使用aspectj的@Around注解实现用户操作和操作结果日志
spring中自定义注解(annotation)与AOP中获取注解 一.自定义注解(annotation) 自定义注解的作用:在反射中获取注解,以取得注解修饰的类.方法或属性的相关解释. packag ...
- spring扫描自定义注解并进行操作
今天又个需求,就是根据注解来判断是否接口为对外开放,那么启动spring容器的时候把这些注解修饰的bean name放进缓存当中. /** * 扫描注解添加服务到缓存以供判断时候为对外开放servi ...
- java 扫描自定义注解_利用spring 自定义注解扫描 找出使用自定义注解的类
我们常常有扫描项目里带有指定注解的class, 下面是利用spring扫描自定义注解的方法, 还是比较灵活的 我这里将扫描到的class放到map, 你可以放到其他地方,以便后期使用 import l ...
- java 外部覆盖内部配置,Spring 与自定义注解、外部配置化的结合使用
Spring 与自定义注解.外部配置化的结合使用 一.Java注解的简单介绍 注解,也叫Annotation.标注,是 Java 5 带来的新特性. 可使用范围 类.字段.方法.参数.构造函数.包等, ...
- spring AOP自定义注解方式实现日志管理
转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接 ...
- Spring Security自定义登录验证及登录返回结果
Spring Security自定义登录验证及登录返回结果 一.功能描述 二.处理逻辑 简单流程 自定义UserDetails 自定义UserDetailsDAO 自定义UserDetailsServ ...
- Spring Security——自定义认证错误提示信息及自适应返回格式解决方案
解决方案 package com.hailiu.web.handler;import com.hailiu.model.Log; import com.hailiu.web.bean.Response ...
- sessionattribute 被spring 扫描不到_Spring 系列之 Spring 常用注解总结(肝硬化的干货)...
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1. 如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml ...
最新文章
- SAP UI5 jQuery.sap.getModulePath 的工作原理
- 基于java+springboot+layui的流浪动物交流信息平台设计实现
- DT时代释放金融数据价值,驱动金融商业裂变
- 线程范围内的线程共享(多线程)
- 3. SQL 语句本身的优化(慢查询)
- ubuntu16.04 修改分辨路并永久保存
- 免费学plc的手机app_PLC网校app手机版 v1.2
- 台达变频器485通讯接线图_台达变频器RS485通讯设置
- 看了三篇韩寒的博客文章
- Python程序设计实验——2.掷骰子游戏
- 连续分配管理方式(单一连续分配 固定分区分配 动态分区分配)
- Kaldi 实践与探索 语音识别基本法 pdf
- 在线更换背景网站(白色背景换为蓝色背景证件照)
- 专访王豫翔:编程道路上的“三少三多”(摘录)
- 回顾使用云桌面的那些经验
- html 拉伸幕,html 对 div 进行 拉伸 拖拽
- python获取列表数字的下标
- flutter图片聊天泡泡_Flutter 非常丰富的消息气泡效果合集
- BigDecimal类型数据比较大小的方法和精度问题
- 安徽工业大学计算机考研调剂,安徽工业大学考研调剂
热门文章
- dubbo总结——dubbo的使用场景
- 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍
- Linux的简单Nginx
- 关于ubuntu 16.04 docker常用命令
- [转]JDBC中日期时间的处理技巧
- 深入了解一下PYTHON中关于SOCKETSERVER的模块-C
- 浏览器拦截弹出窗口 IE Firefox……浏览器
- Oracle 10g新增DROP DATABASE命令
- C#使用ExecuteReader返回DataReader既有查询结果集又有输出参数或返回值的使用注意事项...
- 云栖大会变迁史(2009-2017)