最近项目中遇到一个业务场景,就是在Spring容器启动后获取所有的Bean中实现了一个特定接口的对象,第一个想到的是ApplicationContextAware,在setApplicationContext中去通过ctx获取所有的bean,后来发现好像逻辑不对,这个方法不是在所有bean初始化完成后实现的,后来试了一下看看有没有什么Listener之类的,发现了好东西ApplicationListener,然后百度一下ApplicationListener用法,原来有一大堆例子,我也记录一下我的例子好了。

很简单,只要实现ApplicationListener<ContextRefreshedEvent>接口,然后把实现类进行@Component即可,代码如下:

  1. <span style="font-size: 16px;">@Component
  2. public class ContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
  3. @Override
  4. public void onApplicationEvent(ContextRefreshedEvent event) {
  5. // 根容器为Spring容器
  6. if(event.getApplicationContext().getParent()==null){
  7. Map<String,Object> beans = event.getApplicationContext().getBeansWithAnnotation(IMobile.class);
  8. for(Object bean:beans.values()){
  9. System.err.println(bean==null?"null":bean.getClass().getName());
  10. }
  11. System.err.println("=====ContextRefreshedEvent====="+event.getSource().getClass().getName());
  12. }
  13. }
  14. }</span>

其中,通过event.getApplicationContext().getBeansWithAnnotation获取到所有拥有特定注解的Beans集合,然后遍历所有bean实现业务场景。

总结思考:这样的功能可以实现系统参数的初始化,获取系统中所有接口服务清单等一系列需要在Spring启动后初始化的功能。

延生一下:除了以上启动后事件外,还有其他三个事件

Closed在关闭容器的时候调用,

Started理论上在容器启动的时候调用,

Stopped理论上在容器关闭的时候调用。

我通过TomcatServer进行启动停止,只看到了Refreshed和Closed,不知道为啥,有空再继续研究

spring中如何获取注入bean里方法上的注解?

有这样一个需求,在spring中,想用反射获取一个注入bean中方法的注解
一般情况下这样的操作就行了:
Method method = bean.getClass().getMethod(...);
Annotation[] annotations = method.getAnnotations();
这样就能获取注解了。

spring中如何获取bean的成员变量上的注解?

package com.vweb.util;

import com.vweb.webapp.Mouse;
import com.vweb.webapp.MyAnno;
import com.vweb.webapp.TestUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List; public class IntactCheckUtil { public static boolean check(Object obj){
// list = Arrays.asList(AnnotationParsing.class.getClassLoader().loadClass(((Class)obj).getClass().getName()).getDeclaredFields());
List<Field> list = Arrays.asList(obj.getClass().getDeclaredFields());
for(int i=;i<list.size();i++){
Field field = list.get(i);
if(field.isAnnotationPresent(MyAnno.class)){//是否使用MyAnno注解
for (Annotation anno : field.getDeclaredAnnotations()) {//获得所有的注解
if(anno.annotationType().equals(MyAnno.class) ){//找到自己的注解
if(!((MyAnno)anno).isCanNull()){//注解的值
if(TestUtil.getFieldValueByName(field.getName(),obj)==null){
throw new RuntimeException("类:"+Mouse.class+"的属性:"+field.getName()+"不能为空,实际的值:"+TestUtil.getFieldValueByName(field.getName(),obj)+",注解:field.getDeclaredAnnotations()");
}
}
if(!((MyAnno)anno).isCanEmpty()){
if(TestUtil.getFieldValueByName(field.getName(),obj).equals("")){
throw new RuntimeException("类:"+Mouse.class+"的属性:"+field.getName()+"不能为空字符串,实际的值:"+TestUtil.getFieldValueByName(field.getName(),obj)+",注解:field.getDeclaredAnnotations()");
}
}
if(!((MyAnno)anno).isCanZero()){
if(TestUtil.getFieldValueByName(field.getName(),obj).toString().equals("0") || TestUtil.getFieldValueByName(field.getName(),obj).toString().equals("0.0")){
throw new RuntimeException("类:"+Mouse.class+"的属性:"+field.getName()+"不能为空字符0,实际的值:"+TestUtil.getFieldValueByName(field.getName(),obj)+",注解:field.getDeclaredAnnotations()");
}
}
}
}
} }
return true;
}
}

备注:注解各参数的使用(以下内容来自互联网http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html)

java 反射得到属性与属性值

/**
* 得到属性值
* @param obj
*/
public static void readAttributeValue(Object obj){
String nameVlues="";
//得到class
Class cls = obj.getClass();
//得到所有属性
Field[] fields = cls.getDeclaredFields();
for (int i=0;i<fields.length;i++){//遍历
try {
//得到属性
Field field = fields[i];
//打开私有访问
field.setAccessible(true);
//获取属性
String name = field.getName();
//获取属性值
Object value = field.get(obj);
//一个个赋值
nameVlues += field.getName()+":"+value+",";
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}       //获取最后一个逗号的位置       int lastIndex = nameVlues.lastIndexOf(",");    
//不要最后一个逗号","
String result= nameVlues.substring(0,lastIndex);
System.out.println(result);
}

@Target:

   @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。

    取值(ElementType)有:

    1.CONSTRUCTOR:用于描述构造器
    2.FIELD:用于描述域
    3.LOCAL_VARIABLE:用于描述局部变量
    4.METHOD:用于描述方法
    5.PACKAGE:用于描述包
    6.PARAMETER:用于描述参数
    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。

  取值(RetentionPoicy)有:

    1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)
    3.RUNTIME:在运行时有效(即运行时保留)

 @Documented:

  该属性用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

@Inherited:

  @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

  注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。

  当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

自定义注解:

  使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

  定义注解格式:
  public @interface 注解名 {定义体}

  注解参数的可支持数据类型:

    1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
    2.String类型
    3.Class类型
    4.enum类型
    5.Annotation类型
    6.以上所有类型的数组

  Annotation类型里面的参数该怎么设定: 
  第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;   
  第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;  
  第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。

Spring启动后获取所有拥有特定注解的Bean,注解的属性值的更多相关文章

  1. ApplicationListener<ContextRefreshedEvent>接口,Spring启动后获取所有拥有特定注解的Bean

    最近项目中遇到一个业务场景,就是在Spring容器启动后获取所有的Bean中实现了一个特定接口的对象,第一个想到的是ApplicationContextAware,在setApplicationCon ...

  2. spring练习,使用Eclipse搭建的Spring开发环境,使用set注入方式为Bean对象注入属性值并打印输出。

    相关 知识 >>> 相关 练习 >>> 实现要求: 使用Eclipse搭建的Spring开发环境,使用set注入方式为Bean对象注入属性值并打印输出.要求如下: ...

  3. spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  4. Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

    1.Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理 2. 自定义注解: 使用@interfac ...

  5. 随手记一次用C#正则表达式获取下拉菜单html标签<select>以及相关属性值

    随手记一次用C#正则表达式获取下拉菜单html标签<select>以及相关属性值 1:有如下html: .................. <select id="aaa ...

  6. Spring启动时获取自定义注解的属性值

    1.自定义注解 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documen ...

  7. 在spring启动后执行代码

    如果spring的项目直接监听tomcat启动对于 操作来说有很大难度,bean没有初始化,接口不能直接调用等等,所以我们代码执行要在spring启动之后执行项目 package com.java71 ...

  8. Spring之使用注解实例化Bean并注入属性

    1.准备工作 (1)导入jar包 除了上篇文章使用到的基本jar包外,还得加入aop的jar包,所有jar包如下 所需jar包 (2)配置xml <?xml version="1.0& ...

  9. [转]Spring注解-@Configuration注解、@Bean注解以及配置自动扫描、bean作用域

    1.@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,作用为:配置spring容器(应用上下文) package com.test.s ...

随机推荐

  1. LinuxKit

    LinuxKit是Docker最新发布的一个用于为容器构建安全.便携.可移植操作系统的工具包.它根据用户编写的yaml(指定kernel和基于docker image的一些列服务)自动构建一个常见虚拟 ...

  2. antd 表单双向绑定的研究

    痛点 在使用antd的表单时,大家觉得不够清爽,总结如下: 大量的模板语法,需要一定的学习成本. 需要手动地进行数据绑定,使用大量的onChange/setFieldsValue去控制数据. 无法通过 ...

  3. 拖拽窗口的实现-JQuery实现;

    主要是距离的掌握 如图,原始位置和当前位置. 对于当前位置:想要求得left值b',需要b'=a'-c; 其中,a’= ev.pageX;就是指针当前距离文档左边的距离: 同时,可以发现c在拖拽过程中 ...

  4. RedHat设置Yum源

    Linux:RedHat AS 6.2的版本 1.删除原有的yum: rpm -aq | grep yum | xargs rpm -e –nodeps 2.安装新的yum <1>rpm ...

  5. Kinect 2.0 默认姿势的中文意思

    RaiseRightHand/RaiseLeftHand 抬起左右手高于肩膀一秒Psi 举起双手高于肩膀一秒Tpose T姿势Stop 右手放下,左手缓慢贴住身侧(腰以下)或者左右调换Wave 挥手 ...

  6. day5-随机数相关:random模块&string模块

    一.概述 随机数在程序设计中的属于比较基础的内容,主要用于验证场景(如验证码,生成账号对应的密码等),今天结合random模块和string模块来谈谈python中随机数那些事儿. 二.随机数实现相关 ...

  7. 19-THREE.JS 深度材质

    <!DOCTYPE html> <html> <head> <title></title> <script src="htt ...

  8. 剑指offer--25.二叉树的镜像

    时间限制:1秒 空间限制:32768K 热度指数:238655 题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 ...

  9. 【python】类file文件处理

    [flush方法] 通常由于缓冲,write不将数据写入文件,而是写入内存的缓冲区,需要使用flush写入文件,并清空缓冲区 文件的flush方法的作用是强制清空缓存写入文件.默认每行flush一下? ...

  10. 《锋利的jQuery》读书笔记(动画)

    1.show()和hide() 实质就是改变当前DOM对象的display为block.none或inline-block(取决于之前的display),如下: $("element&quo ...