本文是对参考连接的一个补充,只讨论@within
和@target
的区别。如果不懂注解的、不懂AOP的先去补一下。
参考连接
概述
@within
和@target
是在配置切点的时候使用到的两个修饰符,都是基于注解来配置切点。
比如当前有注解@A
"@within(com.annotation.other.A1)"
该配置就是:如果某个类上标注了注解@A
,那么该类中的所有方法就会被匹配为切点,并且该类的子类中没有重写的父类方法也会被匹配为切点(看不懂的别急,后面有例子)"@target(com.annotation.other.A1)"
该配置就是:如果某个类上标注了注解@A
,那么该类中的所有方法就会被匹配为切点。
约定
本文说的子类和父类关系都是类之间的子类和父类。不涉及注解继承,也就是自定义注解中没有标注元注解–@Inherited。
@within
和@target
正确用法是"@within/@target(注解的全类名)"
,以下简写为"@within/@target(@A1)"
实例
类图
两个自定义注解
//注解@A1@Retention(RetentionPolicy.RUNTIME)@Target( ElementType.TYPE)public @interface A1 {}//注解@A2@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface A2 {}
三个有继承关系的类
@A1public class Human {public void say(String sentence){System.out.println("Human says:" + sentence);}public void run(){System.out.println("Human runs." );}public void jump(){System.out.println("Human jump." );}}@A2public class Man extends Human{@Overridepublic void run(){System.out.println("Man runs." );}public void testMan(){System.out.println("Man testMan." );}}public class Boy extends Man{@Overridepublic void jump(){System.out.println("Boy jump." );}public void test(){System.out.println("Bot test...");}}
切面
@Aspect@Componentpublic class HumanAspect {@Before("@within(com.annotation.other.A1)")public void execute1(){System.out.println("@within --- A1");}@Before("@target(com.annotation.other.A1)")public void execute2(){System.out.println("@target --- A1");}@Before("@within(com.annotation.other.A2)")public void execute3(){System.out.println("@within --- A2");}@Before("@target(com.annotation.other.A2)")public void execute4(){System.out.println("@target --- A2");}}
配置类
@Configuration@ComponentScan("com.annotation.other")@EnableAspectJAutoProxypublic class HumanManager {@Bean(name = "human")public Human getHuman() {return new Human();}@Bean(name = "man")public Man getMan() {return new Man();}@Bean(name = "boy")public Boy getBoy() {return new Boy();}}
输出结果
--------------- This is a Human ---------------@within --- A1@target --- A1Human says:hello!@within --- A1@target --- A1Human jump.@within --- A1@target --- A1Human runs.---------------------This is a Man ---------------@within --- A1@target --- A2Human says:hello!@within --- A1@target --- A2Human jump.@within --- A2@target --- A2Man runs.---------------------This is a Boy ---------------@within --- A1Human says:hello!Boy jump.@within --- A2Man runs.Bot test...
结合类图来分下下输出结果
对于Human方法的输出情况。可以确定的是,如果类上标注了@within
和@target
指定的注解,那么该类的所有方法就会被匹配为切点。
对于Man方法的输出情况,Man只标有注解@A2
,Man的父类标有注解@A1
。
- 继承了父类,但没有重写的方法会被@within(@A1)
匹配为切点,不会被@target(@A1)
匹配。
- 继承父类并在子类重写的方法不会被@within(@A1)
匹配为切点,也不会被@target(@A1)
匹配为切点。
- 对于@within(@A2)、@target(@A2)
会匹配Man类中非继承或继承但重写或自己的方法为切点。
对于Boy类输出情况,Boy类上没有注解,Boy继承了Man类,Man类继承了Human类。Man类表有注解@A2
,Human类标有注解@A1
。 Boy重写了属于Human类的jump()
方法,Boy类有自己的方法test()
。
@winthin(@A1)
匹配了Boy类继承Human类但并未重写的方法,@winthin(@A2)
匹配了继承自Man类但并为重写的方法。
总结
对于匹配不具有继承性且为运行时的注解
即被匹配注解标注了@Retention(RetentionPolicy.RUNTIME),但没有标注
@Inherited
@within
会匹配到标注了指定注解的类,并且在该类的子类中,那些没有重写的父类方法也会被匹配到。-@target
只匹配标注了指定注解的类。不涉及任何其他类。