• 笔记9 AOP练习3(通过注解引入新功能 )


    切面可以为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

  • 相关阅读:
    拉普拉斯矩阵
    正定矩阵 和 半正定矩阵
    Random Walk
    论文解读(DGI)《DEEP GRAPH INFOMAX》
    python安装easyinstall/pip出错
    pip国内源设置
    在Jupyter Notebook添加代码自动补全功能
    [BUUCTF]PWN——bjdctf_2020_babystack2
    [BUUCTF]REVERSE——[BJDCTF 2nd]8086
    [BUUCTF]PWN——jarvisoj_tell_me_something
  • 原文地址:https://www.cnblogs.com/lyj-gyq/p/8886259.html
Copyright © 2020-2023  润新知