本文是对参考连接的一个补充,只讨论@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 {
}
三个有继承关系的类
@A1
public 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." );
}
}
@A2
public class Man extends Human{
@Override
public void run()
{
System.out.println("Man runs." );
}
public void testMan(){
System.out.println("Man testMan." );
}
}
public class Boy extends Man{
@Override
public void jump()
{
System.out.println("Boy jump." );
}
public void test(){
System.out.println("Bot test...");
}
}
切面
@Aspect
@Component
public 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")
@EnableAspectJAutoProxy
public 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 --- A1
Human says:hello!
@within --- A1
@target --- A1
Human jump.
@within --- A1
@target --- A1
Human runs.
---------------------This is a Man ---------------
@within --- A1
@target --- A2
Human says:hello!
@within --- A1
@target --- A2
Human jump.
@within --- A2
@target --- A2
Man runs.
---------------------This is a Boy ---------------
@within --- A1
Human says:hello!
Boy jump.
@within --- A2
Man 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
只匹配标注了指定注解的类。不涉及任何其他类。