1.定义注解接口
import java.lang.annotation.*; @Documented @Inherited @Target({ ElementType.FIELD, ElementType.METHOD ,ElementType.TYPE_USE,ElementType.ANNOTATION_TYPE,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface RedisHandel { String key() default ""; String keyField() default "username"; }
@Target({ElementType.TYPE}) 注解
ElementType 这个枚举类型的常量提供了一个简单的分类:注释可能出现在Java程序中的语法位置(这些常量与元注释类型(@Target)一起指定在何处写入注释的合法位置)
package java.lang.annotation; /** * The constants of this enumerated type provide a simple classification of the * syntactic locations where annotations may appear in a Java program. These * constants are used in {@link Target java.lang.annotation.Target} * meta-annotations to specify where it is legal to write annotations of a * given type. * @author Joshua Bloch * @since 1.5 * @jls 9.6.4.1 @Target * @jls 4.1 The Kinds of Types and Values */ public enum ElementType { /** 类, 接口 (包括注释类型), 或 枚举 声明 */ TYPE, /** 字段声明(包括枚举常量) */ FIELD, /** 方法声明(Method declaration) */ METHOD, /** 正式的参数声明 */ PARAMETER, /** 构造函数声明 */ CONSTRUCTOR, /** 局部变量声明 */ LOCAL_VARIABLE, /** 注释类型声明 */ ANNOTATION_TYPE, /** 包声明 */ PACKAGE, /** * 类型参数声明 * * @since 1.8 */ TYPE_PARAMETER, /** * 使用的类型 * * @since 1.8 */ TYPE_USE }
@Retention({RetentionPolicy.Runtime}) 注解
RetentionPolicy这个枚举类型的常量描述保留注释的各种策略,它们与元注释(@Retention)一起指定注释要保留多长时间
package java.lang.annotation; /** * Annotation retention policy. The constants of this enumerated type * describe the various policies for retaining annotations. They are used * in conjunction with the {@link Retention} meta-annotation type to specify * how long annotations are to be retained. * * @author Joshua Bloch * @since 1.5 */ public enum RetentionPolicy { /** * 注释只在源代码级别保留,编译时被忽略 */ SOURCE, /** * 注释将被编译器在类文件中记录 * 但在运行时不需要JVM保留。这是默认的 * 行为. */ CLASS, /** *注释将被编译器记录在类文件中 *在运行时保留VM,因此可以反读。 * @see java.lang.reflect.AnnotatedElement */ RUNTIME }
@Documented注解
Documented注解表明这个注释是由 javadoc记录的,在默认情况下也有类似的记录工具。 如果一个类型声明被注释了文档化,它的注释成为公共API的一部分。
@Inherited注解
它也是一个标记注解,它的作用是,被它标注的类型是可被继承的,比如一个class被@Inherited标记,那么一个子类继承该class后,则这个annotation将被用于该class的子类。
注意:父类的类上和方法上有自定义注解,并且被@Inherited标记,那么子类只有继承的情况下才会继承父类注解。重写,重载,实现父类方法这些都不会继承父类注解。
2.通过切面来实现注解
@Aspect @Configuration public class RedisAspect { // //定义切点方法 @Pointcut("@annotation(com.ethendev.wopihost.annotation.RedisHandel)") public void pointCut(){} //环绕通知 @Around("pointCut()") public void around(ProceedingJoinPoint joinPoint) { try{ //1.获取到所有的参数值的数组 Object[] args = joinPoint.getArgs(); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; //2.获取到方法的所有参数名称的字符串数组 String[] parameterNames = methodSignature.getParameterNames(); Method method = methodSignature.getMethod(); System.out.println("---------------参数列表开始-------------------------"); for (int i =0 ,len=parameterNames.length;i < len ;i++){ System.out.println("参数名:"+ parameterNames[i] + " = " +args[i]); } System.out.println("---------------参数列表结束-------------------------"); RedisHandel redis=(RedisHandel)method.getAnnotation(RedisHandel.class); System.out.println("自定义注解 key:" + redis.key()); System.out.println("自定义注解 keyField:" + redis.keyField()); Class cla=method.getClass(); if(cla.isAnnotationPresent(RedisHandel.class)){ RedisHandel redisHandel =(RedisHandel)cla.getAnnotation(RedisHandel.class); String key=redisHandel.key(); String keyField=redisHandel.keyField(); System.out.println("key = " + key); System.out.println("keyField = " + keyField); } }catch (Exception e){ e.printStackTrace(); } } }
@Aspect:切面。表示一个横切进业务的一个对象。它里面包含切入点(Pointcut)和Advice(通知)。
@Pointcut:切入点。表示需要切入的位置,比如某些类或者某些方法,也就是先定一个范围。
@Before:Advice(通知)的一种,切入点的方法体执行之前执行。
@Around:Advice(通知)的一种,环绕切入点执行也就是把切入点包裹起来执行。
@After:Advice(通知)的一种,在切入点正常运行结束后执行。
@AfterReturning:Advice(通知)的一种,在切入点正常运行结束后执行,异常则不执行
@AfterThrowing:Advice(通知)的一种,在切入点运行异常时执行。
3、service层中使用
(注意 自定义注解失效可能你的bean或方法未纳入spring范围)
比如:
service层写法:
@Service public class Test { @RedisHandel(key = "kkkk" ,keyField = "param1") public String test(String abc,int i8,int i2, String str ,Integer i){ return "1"; } }
controller写法:
@GetMapping("/hello") public String hello(){ //这个会失效 meTest("德玛西亚",1); //这个通过Autowird service层的方法就不会失效 @Autowired Test test; test.test("德邦总管",1,2,"德玛西亚皇子",3); return "hello"; } @RedisHandel(key = "kkkk" ,keyField = "param1") private void meTest(String str ,Integer i){ System.out.println(str); System.out.println(i); }
以下为测试效果:
总结:如果你的注解在启动类加了@EnableAspectJAutoProxy 配置文件加了
spring.aop.proxy-target-class=true注解依旧无效的话,可能就是注解用的方法存在注解无法被spring管理的原因。
还没有评论,来说两句吧...