Spring AOP @within和@target使用示例及对比分析
@within:使用“@within(注解类型)”匹配所有持有指定注解类型内的方法
注解类型也必须是全限定类型名
模式 | 描述 |
---|---|
@within(com.learn.annotation.Secure) |
任何目标对象对应的类型持有Secure注解的类方法; 必须是在目标对象上声明这个注解, 在接口上声明的对它不起作用 |
@target:使用“@target(注解类型)”匹配当前目标对象类型的执行方法
其中目标对象持有指定的注解,注解类型也必须是全限定类型名
模式 | 描述 |
---|---|
@target(com.learn.annotation.Secure) |
任何目标对象持有Secure注解的类方法; 必须是在目标对象上声明这个注解,在接口上声明的对它不起作用 |
-
创建注解
- 创建package命名为
com.learn.annotation
(根据实际情况修改) - 创建注解
Secure
,内容如下@Documented @Retention(RetentionPolicy.RUNTIME) @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) public @interface Secure { }
- 创建package命名为
-
创建组件
创建package命名为
com.learn.model
(根据实际情况修改)-
创建抽象类
User
,内容如下public abstract class User { public abstract void who(); public void say() { System.out.println("hello"); } public void root() { System.out.println("user"); } }
-
创建组件
Member
,内容如下@Component @Secure public class Member extends User{ @Override public void who() { System.out.println("member"); } public void doSomething() { System.out.println("member doSomething"); } public void getCompany() { System.out.println("zero tec"); } }
-
创建组件
Leader
,内容如下@Component public class Leader extends Member{ @Override public void say() { System.out.println("hello, members"); } @Override public void who() { System.out.println("leader"); } @Override public void doSomething() { System.out.println("leader doSomething"); } public void self() { System.out.println("leader self"); } }
-
创建AOP
- 创建package命名为
com.learn.aop
(根据实际情况修改) - 配置AOP,新建
ExecutionAOP
,内容如下@Aspect @Component public class ExecutionAop { @Before("@within(com.learn.annotation.Secure)") public void execute1(){ System.out.println("@within(com.learn.annotation.Secure)"); } @Before("execution(* com.learn..*(..)) && @target(com.learn.annotation.Secure)") public void execute2(){ System.out.println("@target(com.learn.annotation.Secure)"); } }
- 创建package命名为
-
创建测试用例
@RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTests { @Resource private Member member; @Resource private Leader leader; // 实现 @Test public void test1() { System.out.println("---------------member---------------"); member.who(); System.out.println("---------------leader---------------"); leader.who(); } @Test public void test2() { // 继承 System.out.println("---------------member---------------"); member.say(); // 重载 System.out.println("---------------leader---------------"); leader.say(); } @Test public void test3() { System.out.println("---------------member---------------"); member.root(); System.out.println("---------------leader---------------"); leader.root(); } @Test public void test4() { // 独有方法 System.out.println("---------------member---------------"); member.doSomething(); // 子类重写 System.out.println("---------------leader---------------"); leader.doSomething(); } @Test public void test5() { System.out.println("---------------member---------------"); member.getCompany(); System.out.println("---------------leader---------------"); leader.getCompany(); } // 独有的方法 @Test public void test6() { System.out.println("---------------leader---------------"); leader.self(); } }
-
运行test1可得到结果
---------------member--------------- @within(com.learn.annotation.Secure) @target(com.learn.annotation.Secure) member ---------------leader--------------- leader
由结果可知,对于重载的方法,没有注解的子类,@within和@target都不会匹配到。
有注解的子类可以匹配到重载的方法。 -
运行test2可得到结果
---------------member--------------- @target(com.learn.annotation.Secure) hello ---------------leader--------------- hello, members
由结果可知,对于有注解的子类。
没有重载的方法@within匹配不到,但是@target可以匹配到 -
运行test3可得到结果
---------------member--------------- @target(com.learn.annotation.Secure) user ---------------leader--------------- user
和结论2一样
-
运行test4可得到结果
---------------member--------------- @within(com.learn.annotation.Secure) @target(com.learn.annotation.Secure) member doSomething ---------------leader--------------- leader doSomething
由结果可知,再次证明@within和@target都没有被继承
-
运行test5可得到结果
@within(com.learn.annotation.Secure) @target(com.learn.annotation.Secure) zero tec ---------------leader--------------- @within(com.learn.annotation.Secure) zero tec
由结果可知,子类继承并没有重新父类方法时,该方法可以被@within匹配到。
-
运行test6可得到结果
---------------leader--------------- leader self
由结果可知,再次证明@within和@target都不能对子类的方法生效
总结:
- 父类有注解,但子类没有注解的话,@within和@target是不会对子类生效的。
- 子类没有注解的情况下,只有没有被重写的有注解的父类的方法才能被@within匹配到。
- 如果父类无注解,子类有注解的话,@target对父类所有方法生效,@within只对重载过的方法生效。
回顾一下之前的target和this:
- 两者都可继承。
- 但是对于目标子类,未重载的父类方法是不能被this匹配到的。
-