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匹配到的。
-