切面可以为Spring bean添加新方法。 在Spring中,切面只是实现了它们所包装bean相同接口的 代理。如果除了实现这些接口,代理也能暴露新接口的话,会怎么样 呢?那样的话,切面所通知的bean看起来像是实现了新的接口,即便 底层实现类并没有实现这些接口也无所谓。

使用Spring AOP,我们可以为bean引入新的方法。 代理拦截调用并委托给实现该方法的其他对象

需要注意的是,当引入接口的方法被调用时,代理会把此调用委 托给实现了新接口的某个其他对象。实际上,一个bean的实现被拆分 到了多个类中。

场景描述:

    在一场音乐会中,添加川剧变脸的环节,但在原来的古典音乐表演类(Classcial.java)中没有这个方法,所以需要为这个表演类再新加一个方法。

1.创建一个新的接口Encoreable.java

 package concert2;

 public interface Encoreable {
void performEncore();
}

2.实现这个接口DefaultEncoreable.java

 package concert2;

 public class DefaultEncoreable implements Encoreable {

     @Override
public void performEncore() {
// TODO Auto-generated method stub
System.out.println("川剧变脸");
} }

3.创建一个用于注入新方法的切面EncoreableIntroducer.java

 package concert2;

 import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component; @Aspect
@Component
public class EncoreableIntroducer {
@DeclareParents(value = "concert2.Performance+", defaultImpl = DefaultEncoreable.class)
public static Encoreable encoreable;
}

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

 package concert2;

 import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration
@EnableAspectJAutoProxy // 启用AspectJ自动代理
@ComponentScan
public class ConcertConfig { }

4.测试

在此做了对比,因为Encoreable已经声明为bean,所以也可以直接加载,然后调用其方法。其次,因为Encoreable的方法已经添加到Performance中,所以也可以通过Performance的对象进行调用,但需要注意的是,在调用新加入的方法时要进行“伪装”,即将Performance的对象强制转换为Encoreable,然后再调用新加入的方法,以逃过编译器的检查。如果不进行引入的话,强行改变Performance对象的类型,然后调用“新方法”,则会报错。

 package concert2;

 import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = concert.ConcertConfig.class)
public class ConcertTest {
@Autowired
public Performance p;
@Autowired
public Encoreable en;
@Test
public void test() {
p.perform();
System.out.println("-----------------------------");
System.out.println("自己创建对象调用");
en.performEncore();
System.out.println("-----------------------------");
System.out.println("通过Performance对象调用“新方法”");
Encoreable e = (Encoreable) p;
e.performEncore();
}
}

5.结果

省略的部分请参照笔记7

笔记9 AOP练习3(通过注解引入新功能 )的更多相关文章

  1. Spring实战(十)Spring AOP应用——为方法引入新功能、为对象引入新方法

    切面最基本的元素是通知和切点,切点用于准确定位应该在什么地方应用切面的通知. 1.Spring借助AspectJ的切点表达式语言来定义Spring切面 在Spring中,要使用AspectJ的切点表达 ...

  2. 【Spring实战】—— 11 通过AOP为特定的类引入新的功能

    如果有这样一个需求,为一个已知的API添加一个新的功能. 由于是已知的API,我们不能修改其类,只能通过外部包装.但是如果通过之前的AOP前置或后置通知,又不太合理,最简单的办法就是实现某个我们自定义 ...

  3. Kinect开发笔记之二Kinect for Windows 2.0新功能

    这是本博客翻译文档的第一篇文章.笔者已经苦逼的竭尽全力的在翻译了.但无奈英语水平也是非常有限.不正确或者不妥当不准确的地方必定会有,还恳请大家留言或者邮件我以批评指正.我会虚心接受. 谢谢大家.   ...

  4. [置顶] Unity2d引入新功能SpriteAtlas,Sprite新的图集方式

    孙广东  2017.8.3 http://blog.csdn.NET/u010019717 在Unity 2017.1.0f3中引入了 SpriteAtlas 官方文档:  https://docs. ...

  5. Spring总结 4.AOP之为对象添加新功能

    Spring除了提供增强原有功能的方法外,还提供了为一个对象引入新功能的方法.如下: package cn.powerfully.service; public interface IService ...

  6. Spring学习笔记之aop动态代理(3)

    Spring学习笔记之aop动态代理(3) 1.0 静态代理模式的缺点: 1.在该系统中有多少的dao就的写多少的proxy,麻烦 2.如果目标接口有方法的改动,则proxy也需要改动. Person ...

  7. Spring的AOP基于AspectJ的注解方式开发2

    参考自黑马培训机构 上一篇博客提到了在配置文件中开启aop的注解开发,以及简单使用了@Before,@Aspect 这是为了告诉spring为前置通知和切面类 接下来介绍aop的注解的通知类型,和切入 ...

  8. Spring的AOP基于AspectJ的注解方式开发1

    参考自黑马培训机构 创建项目,引入jar包 编写目标类,切面类并完成配置 package spring.day2_aop2; /* * 编写目标类 */ public class OrderDao { ...

  9. Spring学习笔记2—AOP

    1.AOP概念 AOP(Aspect Oriented Programming):面向切面编程,AOP能够将那些与业务无关,却为业务模块所共同调用的应用(例如事务处理.日志管理.权限控制等)封装起来, ...

随机推荐

  1. excel2003和excel2007文件的创建和读取

    excel2003和excel2007文件的创建和读取在项目中用的很多,首先我们要了解excel的常用组件和基本操作步骤. 常用组件如下所示: HSSFWorkbook excel的文档对象 HSSF ...

  2. 简单介绍 CPU 的工作原理

    1.内部架构 CPU 的根本任务就是执行指令,对计算机来说最终都是一串由 0 和 1 组成的序列.CPU 从逻辑上可以划分成 3 个模块,分别是控制单元.运算单元和存储单元 .其内部架构如下: [1] ...

  3. 【深度学习】深入理解ReLU(Rectifie Linear Units)激活函数

    论文参考:Deep Sparse Rectifier Neural Networks (很有趣的一篇paper) Part 0:传统激活函数.脑神经元激活频率研究.稀疏激活性 0.1  一般激活函数有 ...

  4. CentOS 7 PHP-redis扩展安装,浏览器不显示数据及redis无法储存数据常见问题解决办法

    首先使用php -m 可以查看到自己安装了那些扩展. 1.使用wget下载redis压缩包 wget https://github.com/phpredis/phpredis/archive/deve ...

  5. 帧动画的创建方式 - xml方式

    废话不多说,先看东西   创建帧动画1 - xml方式 帧动画的创建方式主要以下2种: * 用xml创建动画: * 用代码创建动画:   本文内容主要关注 xml文件 创建帧动画的方式   xml文件 ...

  6. python-map的用法

    map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 1.当seq只 ...

  7. Cookie、Session登陆验证相关介绍和用法

    一.Cookie和Session 首先.HTTP协议是无状态的:所谓的无状态是指每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应直接影响,也不会直接 ...

  8. mysql导出与导入

    环境 centos6.5 32位 Mysql 5.7.19 导出 mysqldump用法 导出整个数据库 [root@mini2 mysql]# mysqldump -p123456 --databa ...

  9. netty学习--handler传递

    在netty中的处理链pipeline中,事件是按顺序传递的,把自己拟人为netty程序,针对进来(inbound)的请求,会从head开始,依次往tail传递. pipeline采用了链表结构,he ...

  10. 无用代码清除tip

    测试提了个bug过来,说是有个ajax请求报404了. 我一看,后台代码被人删了,问了同事,因为实现机制变了,是应该删,但删多了. 把service和controller都恢复后,一个接口中除了我那个 ...