1. 程式人生 > >筆記9 AOP練習3(通過註解引入新功能 )

筆記9 AOP練習3(通過註解引入新功能 )

inf 描述 family frame sse generated clas soft tro

切面可以為Spring bean添加新方法。 在Spring中,切面只是實現了它們所包裝bean相同接口的 代理。如果除了實現這些接口,代理也能暴露新接口的話,會怎麽樣 呢?那樣的話,切面所通知的bean看起來像是實現了新的接口,即便 底層實現類並沒有實現這些接口也無所謂。

使用Spring AOP,我們可以為bean引入新的方法。 代理攔截調用並委托給實現該方法的其他對象

技術分享圖片

需要註意的是,當引入接口的方法被調用時,代理會把此調用委 托給實現了新接口的某個其他對象。實際上,一個bean的實現被拆分 到了多個類中。

場景描述:

    在一場音樂會中,添加川劇變臉的環節,但在原來的古典音樂表演類(Classcial.java)中沒有這個方法,所以需要為這個表演類再新加一個方法。

1.創建一個新的接口Encoreable.java

1 package concert2;
2 
3 public interface Encoreable {
4     void performEncore();
5 }

2.實現這個接口DefaultEncoreable.java

 1 package concert2;
 2 
 3 public class DefaultEncoreable implements Encoreable {
 4 
 5     @Override
 6     public void performEncore() {
 7         //
TODO Auto-generated method stub 8 System.out.println("川劇變臉"); 9 } 10 11 }

3.創建一個用於註入新方法的切面EncoreableIntroducer.java

 1 package concert2;
 2 
 3 import org.aspectj.lang.annotation.Aspect;
 4 import org.aspectj.lang.annotation.DeclareParents;
 5 import org.springframework.stereotype.Component;
6 7 @Aspect 8 @Component 9 public class EncoreableIntroducer { 10 @DeclareParents(value = "concert2.Performance+", defaultImpl = DefaultEncoreable.class) 11 public static Encoreable encoreable; 12 }

EncoreableIntroducer是一個切面,同時聲明它是一個bean。但是,它與我們 之前所創建的切面不同,它並沒有提供前置、後置或環繞通知,而是 通過@DeclareParents註解,將Encoreable接口引入 到Performance bean中。 @DeclareParents註解由三部分組成:

  • value屬性指定了哪種類型的bean要引入該接口。在本例中,也 就是所有實現Performance的類型。(標記符後面的加號表示 是Performance的所有子類型,而不是Performance本 身。)
  • defaultImpl屬性指定了為引入功能提供實現的類。在這裏, 我們指定的是DefaultEncoreable提供實現。
  • @DeclareParents註解所標註的靜態屬性指明了要引入了接 口。在這裏,我們所引入的是Encoreable接口。

而且在將EncoreableIntroducer聲明為一個bean後,Encoreable也就成為了一個bean。

3.采用java裝配bean ConcertConfig.java

 1 package concert2;
 2 
 3 import org.springframework.context.annotation.ComponentScan;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 6 
 7 @Configuration
 8 @EnableAspectJAutoProxy // 啟用AspectJ自動代理
 9 @ComponentScan
10 public class ConcertConfig {
11 
12 }

4.測試

在此做了對比,因為Encoreable已經聲明為bean,所以也可以直接加載,然後調用其方法。其次,因為Encoreable的方法已經添加到Performance中,所以也可以通過Performance的對象進行調用,但需要註意的是,在調用新加入的方法時要進行“偽裝”,即將Performance的對象強制轉換為Encoreable,然後再調用新加入的方法,以逃過編譯器的檢查。如果不進行引入的話,強行改變Performance對象的類型,然後調用“新方法”,則會報錯。

 1 package concert2;
 2 
 3 import org.junit.Test;
 4 import org.junit.runner.RunWith;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.test.context.ContextConfiguration;
 7 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 8 
 9 @RunWith(SpringJUnit4ClassRunner.class)
10 @ContextConfiguration(classes = concert.ConcertConfig.class)
11 public class ConcertTest {
12     @Autowired
13     public Performance p;
14     @Autowired
15     public Encoreable en;
16     @Test
17     public void test() {
18         p.perform();
19         System.out.println("-----------------------------");
20         System.out.println("自己創建對象調用");
21         en.performEncore();
22         System.out.println("-----------------------------");
23         System.out.println("通過Performance對象調用“新方法”");
24         Encoreable e = (Encoreable) p;
25         e.performEncore();
26     }
27 }

5.結果

技術分享圖片

省略的部分請參照筆記7

筆記9 AOP練習3(通過註解引入新功能 )