Java 自定义注解与注解解析实例
在学习Java之后会遇到很多的注解,有加载JavaBean的注解:@Component,@Service,@Controller;有获取配置文件中数值的注解@Value;有获取Http请求的数据的注解,@RequestBody。通过这些注解,spring扫描这些组件,提供相关的服务。如何自定义注解,满足自己的特定服务呢?
【转】http://blog.csdn.net/mafan121/article/details/50212137
【转】http://www.jianshu.com/p/7c2948f64b1c;深入Spring:自定义注解加载和使用
【转】http://www.jianshu.com/p/9d4bd8955d1a;spring自定义注解的使用和解析
欢迎到GitHub 上下载代码
一、了解元注解
元注解,元:原子,组成其他注解的基础注解。java提供了4种元注解用于注解其他注解。
@Target({ElementType.TYPE})//用于描述注解的使用范围,超出范围时编译失败。
取值类型(ElementType):
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域(成员变量)
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention(RetentionPolicy.RUNTIME)//描述注解的生命周期,即注解的生效范围。
取值范围(RetentionPolicy):
1.SOURCE:在源文件中生效,仅存在java文件中,class文件将会去除注解。
2.CLASS:在class文件中生效,仅保留在class文件中,运行时无法获取注解。
3.RUNTIME:在运行时生效,保留在class文件中且运行时可通过反射机制获取。
@Documented // 用于指定javac生成API时显示该注解信息。
@Inherited // 标明该注解可以由子类继承,及子类可以继承父类的注解。而默认情况下,子类是不继承父类注解的。
二、读取注解
Java通过反射机制解析注解,java在java.lang.reflect包下新增了AnnotatedElement接口, AnnotatedElement是所有注解元素的父接口,所有的注解元素都可以通过某个类反射获取AnnotatedElement对象,该对象有一下4个方法来访问Annotation信息。
(1)<T extends Annotation> T getAnnotation(Class<T> annotationClass)
返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
(2)Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
(3)boolean isAnnotationPresent(Class<?extends Annotation> annotationClass)
判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
(4)Annotation[] getDeclaredAnnotations()
返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
三、自定义JavaBean注解。
自定义注解为
package mydefineComponent; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyDefineComponent { String value() default "";
}
JAVA自定义扫描器继承ClassPathScanningCandidateComponentProvider,ClassPathBeanDefinitionScanner,并在内部添加自定义的TypeFilter。
package mydefineComponent; import java.util.Set; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder; public final class Scanner extends ClassPathBeanDefinitionScanner { public Scanner(BeanDefinitionRegistry registry) {
super(registry);
// TODO Auto-generated constructor stub
} public void registerDefaultFilters() {
this.addIncludeFilter(new AnnotationTypeFilter(MyDefineComponent.class));
} public Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
for (BeanDefinitionHolder holder : beanDefinitions) {
GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
definition.getPropertyValues().add("innerClassName", definition.getBeanClassName());
definition.setBeanClass(FactoryBeanTest.class);
}
return beanDefinitions;
} public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return super.isCandidateComponent(beanDefinition) && beanDefinition.getMetadata()
.hasAnnotation(MyDefineComponent.class.getName());
} }
package mydefineComponent; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; @Component
public class BeanScannerConfigurer implements BeanFactoryPostProcessor, ApplicationContextAware{ private ApplicationContext applicationContext; @Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext; } @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
Scanner scanner = new Scanner((BeanDefinitionRegistry) beanFactory);
scanner.setResourceLoader(this.applicationContext);
scanner.scan("mydefineComponent");
} }
package mydefineComponent; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Enhancer; public class FactoryBeanTest<T> implements InitializingBean, FactoryBean<T> { private String innerClassName; public void setInnerClassName(String innerClassName) {
this.innerClassName = innerClassName;
} @Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub } @Override
public T getObject() throws Exception {
Class innerClass = Class.forName(innerClassName);
if (innerClass.isInterface()) {
return (T) InterfaceProxy.newInstance(innerClass);
} else {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(innerClass);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallback(new MethodInterceptorImpl());
return (T) enhancer.create();
}
} @Override
public Class<?> getObjectType() {
try {
return Class.forName(innerClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
} @Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return true;
} }
package mydefineComponent; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class InterfaceProxy implements InvocationHandler { @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("ObjectProxy execute:" + method.getName());
return method.invoke(proxy, args);
} public static <T> T newInstance(Class<T> innerInterface) {
ClassLoader classLoader = innerInterface.getClassLoader();
Class[] interfaces = new Class[] { innerInterface };
InterfaceProxy proxy = new InterfaceProxy();
return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
}
}
package mydefineComponent; import java.lang.reflect.Method; import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; public class MethodInterceptorImpl implements MethodInterceptor{ @Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("MethodInterceptorImpl:" + method.getName());
return methodProxy.invokeSuper(o, objects);
} }
测试代码:
package mydefineComponent; @MyDefineComponent
public class ScanClass1 { public void print() {
System.out.print("scanclass1");
}
}
package mydefineComponent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyDefineComponentTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext("mydefineComponent");
ScanClass1 scanClass = acc.getBean(ScanClass1.class);
scanClass.print();
}
}
输出:
MethodInterceptorImpl:print
scanclass1
三、自定义的注解 ,可通过Spring快速的获取所有使用该注解的类或方法或属性,以及注解内的值。
自定义一个注解:
package com.my.annotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ ElementType.TYPE, ElementType.METHOD }) //可以用在方法或者类上面
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Fooish { String[] tags() default { "all" };
}
自定义注解的解析功能
package com.my.annotation; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; @Component
public class MyFooishHandler implements ApplicationContextAware, InitializingBean{ private ApplicationContext applicationContext; private List<String> allFooish = new ArrayList<>(); @Override
public void afterPropertiesSet() throws Exception {
scanFooishClass();
scanFooishMethod();
System.out.println(allFooish); } /**
* 查找 用 Fooish 注解的 方法
*/
private void scanFooishMethod() throws Exception{
final Map<String, Object> permissionMap = applicationContext.getBeansWithAnnotation(Fooish.class);
System.out.println("this is permissionMap" + permissionMap.toString());
for (final Object permissionObject : permissionMap.values()) {
final Class<? extends Object> permissionClass = permissionObject.getClass();
final Fooish annotation = permissionClass.getAnnotation(Fooish.class);
if(annotation != null) {
allFooish.addAll(Arrays.asList(annotation.tags()));
}
} } private void scanFooishClass() throws Exception{
final Map<String, Object> controllerMap = applicationContext.getBeansWithAnnotation(Fooish.class);
for (final Object controllerObject : controllerMap.values()) {
final Class<? extends Object> controllerClass = controllerObject.getClass();
for (Method method : controllerClass.getDeclaredMethods()) {
Fooish fooish = method.getAnnotation(Fooish.class);
if (fooish != null) {
allFooish.addAll(Arrays.asList(fooish.tags()));
}
}
} } @Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext; } }
测试:
package com.my.controller; import java.io.File;
import java.io.IOException;
import java.util.List; import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import com.my.annotation.Fooish;
import com.my.model.Student;
import com.my.service.FirstPageService;
import com.my.service.QRCodeUtil; @RestController
@Fooish(tags={"this_is_class"})
public class FirstPageController { @Value(value = "${erweima.location:D:/Workspaces/MyEclipse 2015/entrance/src/main/resources/erweima.png}")
private String imgPath; @Resource
private FirstPageService firstPageService; @RequestMapping(value = "/", method = RequestMethod.GET)
@Fooish(tags={"this_is_method"})
String home() {
return firstPageService.getString();
} }
【参考博客】
1、http://blog.csdn.net/mafan121/article/details/50212137
2、http://www.jianshu.com/p/7c2948f64b1c;深入Spring:自定义注解加载和使用
3、http://www.jianshu.com/p/9d4bd8955d1a;spring自定义注解的使用和解析
Java 自定义注解与注解解析实例的更多相关文章
- Java自定义数据验证注解Annotation
本文转载自:https://www.jianshu.com/p/616924cd07e6 Java注解Annotation用起来很方便,也越来越流行,由于其简单.简练且易于使用等特点,很多开发工具都提 ...
- Java自定义Annotation,通过反射解析Annotation
创建一个自定义的Annotation import java.lang.annotation.*; import java.lang.reflect.Method; @Documented @Targ ...
- java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题
一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...
- java中注解的使用与实例 (二)
java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单.注解(Annotation) 为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后 某个时刻方便地使用这些数据(通过 解 ...
- 【转】java中注解的使用与实例
原文:http://www.cnblogs.com/pepcod/archive/2013/02/20/2918719.html java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单. ...
- java自定义注解注解方法、类、属性等等【转】
http://anole1982.iteye.com/blog/1450421 http://www.open-open.com/doc/view/51fe76de67214563b20b385320 ...
- Java自定义注解和运行时靠反射获取注解
转载:http://blog.csdn.net/bao19901210/article/details/17201173/ java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编 ...
- Java自定义注解Annotation的使用
从 jdk5开始,Java增加了对元数据的支持,也就是Annotation,Annotation其实就是对代码的一种特殊标记,这些标记可以在编译,类加载和运行时被读取,并执行相应的处理.当然刚刚说了, ...
- java自定义注解类
一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import ...
随机推荐
- node升级更新最近稳定版
今天,又发现一个超级简单的升级Node.js的方法.一行命令搞定,省去了重新编译安装的过程. node有一个模块叫n(这名字可够短的...),是专门用来管理node.js的版本的. 首先安装n模块: ...
- 08-SSH综合案例:前台用户模块:注册页面的前台JS校验
这个是MyEclipse设置的问题 把设置去掉就没问题了. 你也可以在每一个input后面加个span来显示提示的信息.这些东西也要提交到后台,后台也是要对这些东西进行校验的.
- iOS正确解决隐藏导航栏后push和pop或dismiss和present闪黑问题
情景: 一级页面不显示导航栏 ,二级页面显示导航栏. 方法一 适用于push/pop: 一级页面中 - (void)viewWillAppear:(BOOL)animated { [super vie ...
- Qt's Undo Framework
Overview of Qt's Undo Framework Introduction Qt's Undo Framework is an implementation of the Command ...
- java反射机制学习代码
根据 http://www.iteye.com/topic/137944 文档进行学习 代码如下: package reflectTest; import java.lang.reflect.*; i ...
- pyspider示例代码一:利用phantomjs解决js问题
本系列文章主要记录和讲解pyspider的示例代码,希望能抛砖引玉.pyspider示例代码官方网站是http://demo.pyspider.org/.上面的示例代码太多,无从下手.因此本人找出一下 ...
- o7 文件和函数
一:文件 1 控制文件内指针的移动 文件内指针移动,只有在t模式下的read(n),n代表的字符的个数 除此之外文件内指针的移动都是以字节为单位的 with open('a.txt',mode ='r ...
- Web挖掘
Web挖掘 Web挖掘的目标是从Web的超链接.网页内容和使用日志中探寻有用的信息.依据Web挖掘任务,可以划分为三种主要类型:Web结构挖掘.Web内容挖掘和Web使用挖掘.Web结构挖掘简单的说就 ...
- 续安装好composer和workerman之后;TP5运行workerman的操作
TP5想要实现时时通讯:首先先安装好composer和workerman,我之前有写一篇安装的方法,在cmd里面安装:tp5手册上面有写cmd命令的代码:接下来是安装好后如何运行的: 首先在项目中建立 ...
- windows7 不能更新,提示:"WindowsUpdate_80240016" "WindowsUpdate_dt000",如何解决?
计算机(右键) ---- 管理 -------- 服务和应用程序 -----服务(找到名称为windows update的服务,并且在windwos update服务右键 选择重新启动 ) 再次安装更 ...