切面可以为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. Windows Powershell脚本执行

    在cmd下执行powershell进入shell模式: 变量定义:$i = 10 $a = ifconfig | findstr "192" Windows下的命令都可以执行如: ...

  2. ( 转 ) 聊一聊C#的Equals()和GetHashCode()方法

    聊一聊C#的Equals()和GetHashCode()方法   博客创建一年多,还是第一次写博文,有什么不对的地方还请多多指教. 关于这次写的内容可以说是老生长谈,百度一搜一大堆.大神可自行绕路. ...

  3. SpringBoot入门:新一代Java模板引擎Thymeleaf(理论)

    Spring Boot 提供了spring-boot-starter-web来为Web开发予以支持,spring-boot-starter-web为我们提供了嵌入的Tomcat以及SpringMVC的 ...

  4. IntelliJ IDEA开发Scala代码,与java集成,maven打包编译

    今天尝试了一下在IntelliJ IDEA里面写Scala代码,并且做到和Java代码相互调用,折腾了一下把过程记录下来. 首先需要给IntelliJ IDEA安装一下Scala的插件,在IDEA的启 ...

  5. logback中批量插入数据库的参考代码

    protected void insertProperties(Map<String, String> mergedMap, Connection connection, long eve ...

  6. SpringBoot(四):banner的控制

    banner在springboot中是一个支持可配(banner的样式,banner的颜色,banner的内容).是否显示. 1)banner显示内容配置: 默认springboot如果在src/re ...

  7. 收藏:视频网站(JavaEE+FFmpeg)/Nginx+ffmpeg实现流媒体直播点播系统

    FFmpeg安装(windows环境)http://www.cnblogs.com/xiezhidong/p/6924775.html 最简单的视频网站(JavaEE+FFmpeg)http://bl ...

  8. Struts(二十一):类型转换与复杂属性、集合属性配合使用

    背景: 本章节主要以复杂属性.集合属性类型转化为例,来学习这两种情况下怎么使用. 复杂对象属性转换场景: 1.新建struts_04 web.xml <?xml version="1. ...

  9. Struts(十):OGNL表达式(一)

    Struts2 用s:porperty标签和OGNL表达式来读取值栈中的属性值: I.值栈中的属性值: 1.对象栈:读取对象栈中的某一个对象的属性值: 2.Map栈 :request,session, ...

  10. 类相关的BIF

    1.>>> issubclass(C,A)#判断c是A的子类,返回真假 2.>>> isinstance(b1,B) #判断c1是B类的实例化对象,返回真假 3.& ...