用注解@DelcareParents实现引用增强
引用增强,是一个比较特殊的增强,不同于其他方法级别的增强。
引用增强可以实现:一个Java类,没有实现A接口,在不修改Java类的的情况下,使其具备A接口的功能。
先看看背景,我们有个Love接口:
package com.stuPayment.aopTest;
public interface Love {
public void sayLove();
}
还有一个Greeting接口和我们的GreetingImpl实现类,这两个是我们的目标接口和目标类,GreetingImpl是我们要加强的目标类。:
package com.stuPayment.aopTest;
public interface Greeting {
public void sayHello(String name);
public int saySth();
}
package com.stuPayment.aopTest; import org.springframework.stereotype.Component; @Component
public class GreetingImpl implements Greeting {
@Override
public void sayHello(String name) {
// TODO Auto-generated method stub
System.out.println("hello, " + name);
} @Override
public int saySth() {
// TODO Auto-generated method stub
System.out.println("this is say sth");
return 213;
} }
先看看不用@DeclareParents注解的实现方法:之前的博客中有介绍过这个(之前的随笔“梳理一下我理解的AOP“中有介绍,这里简单说一下”)
比如说我要实现接口Love,类Greeting是没有实现这个接口的,我想利用引用加强让Greeeting实现它,并可以调用Love接口的方法。
首先我需要一个引用加强类:
@Component
public class LoveAdvice extends DelegatingIntroductionInterceptor implements Love () {
....... 要重写的代码还有实现Love接口的代码
}
继承了这个很长的类之后,这个类就变成了引入加强的advice类。
然后配置文件:

然后在测试方法中就可以:
ApplicationContext context = new ClassPathXmlApplicationContext(beans.xml);
GreetingImpl greetingImpl = (GreetingImpl)context.getBean("greetingProxy"); Love love = (Love)greetingImpl;
love.sayLove();
GreetingImpl没有实现Love,但这里我们却可以把它强行转换成Love接口并调用相关的方法。也就是引入增强成功。
然后看我们的@DeclareParents注解的实现方法,这里我是在SpringBoot的环境下。
首先,我们要写个Love接口的实现类:
package com.stuPayment.aopTest;
public class LoveImpl implements Love {
@Override
public void sayLove() {
// TODO Auto-generated method stub
System.out.println("##################### I LOVE ###################");
System.out.println("############# U #############");
System.out.println("################################################");
}
}
然后是引入增强的Aspect类:
package com.stuPayment.aopTest.advice; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component; import com.stuPayment.aopTest.Love;
import com.stuPayment.aopTest.LoveImpl; @Component
@Aspect
public class IntroductionAdviceAspect { @DeclareParents(value = "* com.stuPayment.aopTest.Greeting.*(..)", defaultImpl = LoveImpl.class)
public Love love; }
跟其他Aspect一样,这个类也要@Componemt注解和@Aspect注解。
然后看看@DeclareParents,这里的value和其他的@Before注解的pointcut一样(好像在@DeclareParents只能用value……),然后后面的表达式就类似我们的Pointcut表达式,我这里写的是之前在execution(....)的那些,只是把execution去掉了。这里我这个表达式的意思,就是匹配所有实现了所有Greeting接口的类。
更正:@Declareparents 的vaule应该是描述类的,之前这样写,导致一堆不关事的类都被引入加强了,然后蛮麻烦的。
后面自己试了下,描述实现了Greeting接口的类应该是类似:
@DeclareParents(value = "com.stuPayment.aopTest.Greeting*", defaultImpl = LoveImpl.class)
然后这个defaultImpl写默认的Love接口实现类,就你要找个实现了Love的接口的类写在这。
注解下面写你要加强的那个接口,也就是你要目标类本来没有实现现在又要他实现的那个接口。
然后看我们的测试类:
package com.stuPayment.aopTest; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) // SpringJUnit支持,由此引入Spring-Test框架支持! @SpringBootTest //提供spring环境
public class Test2 { @Autowired
private Greeting greeting; @Test
public void demoIntroductionAdvice() {
Love love = (Love)greeting;
love.sayLove();
greeting.sayHello("Ben");
} }
这个Greeting接口的greeting我们教给Spring容器去管理,之前在GreetingImpl已经有过@Component注释了,这里直接注入就行。
然后运行,结果嗯……报错了:

嗯想到是不是没有设按个spring.aop.proxyTargetClass=true
然后去设了,还是不行……
然后对比了看了下网上的例子,有个例子比我多了这些东西:
一个配置类
package com.stuPayment.aopTest; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @ComponentScan
@Configuration
@EnableAspectJAutoProxy
public class SpringConfig { }
还有在测试类中加入了这行代码,引入了上面那个配置类:
@RunWith(SpringRunner.class) // SpringJUnit支持,由此引入Spring-Test框架支持!
@ContextConfiguration(classes = SpringConfig.class)
@SpringBootTest //提供spring环境
public class Test2 {
然后运行,就可以了:

额这里就有点不明白了,这个@ComponemtScan按道理是SpringBoot肯定是默认开了的啊,不然之前的那些@Controller怎么配置,然后这个@EnableAspectJAutoProxy也是默认开的才对啊在SpringBoot,之前都是直接用注解,而且加了这个配置类之后,把那个Spring.aop.proxyTargetClass=true去掉了也可以。。。。
我想可能是测试环境和SpringBoot的环境的差异吧,先不理了,主要是学习如何通过注解来实现引入增强。
参考博客:
https://blog.csdn.net/elim168/article/details/78166296
https://www.cnblogs.com/xxdsan/p/6496332.html
用注解@DelcareParents实现引用增强的更多相关文章
- Spring系列20:注解详解和Spring注解增强(基础内功)
有部分小伙伴反馈说前面基于注解的Spring中大量使用注解,由于对Java的注解不熟悉,有点难受.建议总结一篇的Java注解的基础知识,那么,它来了! 本文内容 什么是注解? 如何定义注解 如何使用注 ...
- 【Java EE 学习 50】【Spring学习第二天】【使用注解的DI实现】【spring中的继承】【动态代理伪hibernate实现】
一.使用注解的DI实现 1.@Resource 使用该注解能够实现引用型属性的DI实现,该注解能够根据属性名和属性类型自动给属性赋值.一般使用@Resource(name="student& ...
- Spring-AOP 基于注解的实现
一.AOP: 是对OOP编程方式的一种补充.翻译过来为“面向切面编程”. 可以理解为一个拦截器框架,但是这个拦截器会非常武断,如果它拦截一个类,那么它就会拦截这个类中的所有方法.如对一个目标列的代理, ...
- 【SpringAop】【统一日志处理】注解方式理解以及使用
[注意:本次代码的demo会存在百度网盘,由于公司的保密,禁止上传,所以仅本人可见] 目前公司在做数据资产项目,数据质量部分使用到了springaop做统一日志处理,以前对这块有了解,有点模糊不清,今 ...
- 8 -- 深入使用Spring -- 4...5 AOP代理:基于注解的“零配置”方式
8.4.5 基于注解的“零配置”方式 AspectJ允许使用注解定义切面.切入点和增强处理,而Spring框架则可识别并根据这些注解来生成AOP代理.Spring只是使用了和AspectJ 5 一样的 ...
- Spring 中使用XML配置方式和使用注解方式实现DI
Spring容器给我们提供了很好的环境,我们只关注主要业务即可,其他的无需关注太多.今天刚学的DI DI(Dependency Injection):依赖注入 使用XML配置文件完成依赖注入 1.1普 ...
- Spring使用注解实现AOP
一.AspectJ概述 AspectJ是一个面向切面的框架,它扩展了Java语言.定义了AOP语法,能够在编译期提供代码的织入,它提供了一个专门的编译期用来生成遵守字节编码规范的Class文件. @A ...
- spring中的增强类型
在spring中有两种增强方式:XML配置文件和注解配置.下面一次为大家讲解. 使用的是Aspectj第三方框架 纯POJO (在XML中配置节点) 使用@AspectJ,首先要保证所用的JDK 是5 ...
- Spring系列之aAOP AOP是什么?+xml方式实现aop+注解方式实现aop
Spring系列之aop aop是什么?+xml方式实现aop+注解方式实现aop 什么是AOP? AOP为Aspect Oriented Programming 的缩写,意识为面向切面的编程,是通过 ...
随机推荐
- MySQL学习笔记(五)—— 子查询及联结
子查询: 子查询,即嵌套在其他查询中的查询.例如我们有这样几个表,顾客表,订单表,商品表,我们想知道有哪些客户买了商品A,那么我们就需要先查看哪些订单里包含了商品A,然后根据订单查出是哪些客户. my ...
- jmeter中的响应断言
断言就类似LoadRunner中的检查点.对上一个请求返回的信息,做字符串.数据包大小.HTML.XML.图片等做判断,确保返回的信息的准确性. jmeter的断言有好多,下面是一个响应断言 新建一个 ...
- Xamarin.Forms初始
前言 Xamarin.Forms 为 .NET 开发人员提供一个完整的跨平台 UI 工具包. 在 Visual Studio 中使用 C# 生成完全本机的 Android.iOS 和通用 Window ...
- syslog格式
转自:http://wly719.iteye.com/blog/1827394 1.syslog格式介绍 在Unix类操作系统上,syslog广泛 应用于系统日志.syslog日志消息既可以记录在本地 ...
- NOI 2012 魔幻棋盘 | 二维差分 + 二维线段树
题目:luogu 2086 二维线段树,按套路差分原矩阵,gcd( x1, x2, ……, xn ) = gcd( xi , x2 - x1 , ……, xn - xn-1 ),必须要有一个原数 xi ...
- 3.javascript转换日期字符串为Date对象
js中文网 阮一峰 1.求format“xxxx年xx月xx日 xx:xx”类型的两个日期天数差 var start = "2017年09月17日 13:51"; var end ...
- Outlook 开发
转自:http://www.cnblogs.com/madebychina/archive/2011/09/20/madebychina_2.html C#使用如下代码调用Outlook2003发送邮 ...
- 面试题:sql数据查询
前几天参加一个面试,面试公司让做一套题,sql题不是很难,但是我第一次还是写错了,回来后,重新写了下.简单记录下吧, 1.题目: 2.测试数据 select * from student ; inse ...
- 4-1数据类型转换的基本概念 & 4-2 & 4-3数据类型转换案例 & 4-4习题
4-1数据类型转换的基本概念 253是int类型的,赋值给长整型的n 这种就是强制的类型转换 自动类型转换又叫做饮食类型转换,因为他的转换我们是看不到的 实线表示无数据丢失的 虚线在转换时, doub ...
- CodeForces 623B【预处理+DP】
题意: 给出n,a,b以及n个整数a1,a2-an, 可以对数组进行以下两种操作: (1)花费len*a的代价删除连续的len个数,len<|S| (2)花费b的代价将某一个a[i]加一或减一, ...