- 浏览: 15826 次
- 性别:
- 来自: 南京
文章分类
最新评论
基于ProxyFactory的AOP编程
Spring只支持方法连接点,包括了5种类型的增强。
1. 前置异常
这里使用一个服务员作为例子,服务员向顾客打招呼,并且提供服务。首先我们创建一个服务员的接口,然后再创建一个不那么友好的服务员,他直接走到顾客面前就开始提供服务了。我们应该给他们做功课,让他们更加有礼貌一些。
就是这个没什么经验的服务员类:
在这里我们给这个服务加上前置增强类,让这个服务员在见到顾客时先打招呼:
用Spring提供的ProxyFactory进行测试:
输出:
How are you! Mr.John.
greet to John..
How are you! Mr.John.
serve to John..
当然我们也可以采用Spring的方式来配置增强,需要用ProxyFactoryBean来代替上面的ProxyFactory
target:代理的目标对象。
proxyInterfaces:代理所要实现的接口,可以有多个。
interfaces:是上面的属性的别名。
interceptorNames:需要织入目标对象的Bean列表。
singleton:返回的代理是否是单例,默认为单例。
optimize:为true时,使用CGLib代理,否则使用JDK代理。
proxyTargetClass:是否对类进行代理(而不是针对接口进行代理),设置为true时,使用CGLib代理。
让我们来测试一下:
输出:
How are you! Mr.John.
greet to John..
How are you! Mr.John.
serve to John..
2. 后置增强:
在为顾客提供完服务之后,也应该有礼貌。
greet to John..
Please enjoy yourself!
serve to John..
Please enjoy yourself!
3. 环绕增强
Spring在这里直接使用了AOP联盟的接口org.aopalliance.intercept.MethodInterceptor
输出:
How are you! Mr.John.
greet to John..
Please enjoy yourself!
How are you! Mr.John.
serve to John..
Please enjoy yourself!
我们看到方法执行的前后都被织入了增强。
4.异常抛出增强
这里进行配置织入异常抛出增强
****我在采用上面的测试程序进行测试的时候,发现确实在抛出异常之后,走到了增强之中,但是在增强代码结束之后,最终异常还是会被抛出。
4. 引介增强
引介增强和上面的增强都不太一样,可以理解为在运行时为一个类对象添加了新的功能,这将极大地改变我们编写代码时的思路。
这里添加一个新的接口,为性能监视类添加是否需要监控的功能。
这里是增强类
配置文件:
测试程序:
输出:
模拟删除Forum记录:10
模拟删除Topic记录:1022
begin monitor...
模拟删除Forum记录:20
end monitor...
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.removeForum花费20毫秒。
begin monitor...
模拟删除Topic记录:1022
end monitor...
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.removeTopic花费20毫秒。
可以看到在更改可检测属性为true之后,增强才变的有效的。
Spring只支持方法连接点,包括了5种类型的增强。
- 前置增强
- 后置增强
- 环绕增强
- 异常抛出增强
- 引介增强
1. 前置异常
这里使用一个服务员作为例子,服务员向顾客打招呼,并且提供服务。首先我们创建一个服务员的接口,然后再创建一个不那么友好的服务员,他直接走到顾客面前就开始提供服务了。我们应该给他们做功课,让他们更加有礼貌一些。
public interface Waiter { void greetTo(String name); void serveTo(String name); }
就是这个没什么经验的服务员类:
public class NaiveWaiter implements Waiter { public void greetTo(String name) { System.out.println("greet to " + name + ".."); } public void serveTo(String name) { System.out.println("serve to " + name + ".."); } }
在这里我们给这个服务加上前置增强类,让这个服务员在见到顾客时先打招呼:
public class GreetingBeforeAdvice implements MethodBeforeAdvice { public void before(Method method, Object[] args, Object obj) throws Throwable { String clientName = (String) args[0]; System.out.println("How are you! Mr." + clientName + "."); } }
用Spring提供的ProxyFactory进行测试:
public class TestBeforeAdvice { public static void main(String[] args) { Waiter waiter = new NaiveWaiter(); BeforeAdvice advice = new GreetingBeforeAdvice(); ProxyFactory pf = new ProxyFactory(); // 设置目标类 pf.setTarget(waiter); // 设置增强,这里可以添加多个增强 pf.addAdvice(advice); Waiter proxy = (Waiter) pf.getProxy(); proxy.greetTo("John"); proxy.serveTo("John"); } }
输出:
How are you! Mr.John.
greet to John..
How are you! Mr.John.
serve to John..
当然我们也可以采用Spring的方式来配置增强,需要用ProxyFactoryBean来代替上面的ProxyFactory
<bean id="greetingBefore" class="com.firethewhole.maventest07.advice.GreetingBeforeAdvice"/> <bean id="target" class="com.firethewhole.maventest07.advice.NaiveWaiter"/> <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean" p:proxyInterfaces="com.firethewhole.maventest07.advice.Waiter" p:interceptorNames="greetingBefore" p:proxyTargetClass="true" p:target-ref="target"/>
target:代理的目标对象。
proxyInterfaces:代理所要实现的接口,可以有多个。
interfaces:是上面的属性的别名。
interceptorNames:需要织入目标对象的Bean列表。
singleton:返回的代理是否是单例,默认为单例。
optimize:为true时,使用CGLib代理,否则使用JDK代理。
proxyTargetClass:是否对类进行代理(而不是针对接口进行代理),设置为true时,使用CGLib代理。
让我们来测试一下:
String configPath = "com/firethewhole/maventest07/advice/beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter) ctx.getBean("waiter"); waiter.greetTo("John");
输出:
How are you! Mr.John.
greet to John..
How are you! Mr.John.
serve to John..
2. 后置增强:
在为顾客提供完服务之后,也应该有礼貌。
public class GreetingAfterAdvice implements AfterReturningAdvice { public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("Please enjoy yourself!"); } }
<bean id="greetingAfter" class="com.firethewhole.maventest07.advice.GreetingAfterAdvice"/> <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean" p:proxyInterfaces="com.firethewhole.maventest07.advice.Waiter" p:interceptorNames="greetingAfter" p:proxyTargetClass="true" p:target-ref="target"/>
greet to John..
Please enjoy yourself!
serve to John..
Please enjoy yourself!
3. 环绕增强
Spring在这里直接使用了AOP联盟的接口org.aopalliance.intercept.MethodInterceptor
public class GreetingInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { Object[] args = invocation.getArguments(); String clientName = (String) args[0]; System.out.println("How are you! Mr." + clientName + "."); Object obj = invocation.proceed(); System.out.println("Please enjoy yourself!"); return obj; } }
<bean id="greetingAround" class="com.firethewhole.maventest07.advice.GreetingInterceptor"/> <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean" p:proxyInterfaces="com.firethewhole.maventest07.advice.Waiter" p:interceptorNames="greetingAround" p:proxyTargetClass="true" p:target-ref="target"/>
输出:
How are you! Mr.John.
greet to John..
Please enjoy yourself!
How are you! Mr.John.
serve to John..
Please enjoy yourself!
我们看到方法执行的前后都被织入了增强。
4.异常抛出增强
public class ForumServiceThrowException { public void removeForum(int forumId) { throw new RuntimeException("运行异常。"); } public void updateForum(int forumId) throws Exception { throw new SQLException("数据更新操作异常"); } }
public class TransactionManager implements ThrowsAdvice { public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable{ System.out.println("---------------"); System.out.println("method:" + method.getName()); System.out.println("抛出异常:" + ex.getMessage()); System.out.println("成功回滚事务。"); } }
这里进行配置织入异常抛出增强
<bean id="transacionManager" class="com.firethewhole.maventest07.advice.TransactionManager"/> <bean id="forumServiceTarget" class="com.firethewhole.maventest07.advice.ForumServiceThrowException"/> <bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="transacionManager" p:proxyTargetClass="true" p:target-ref="forumServiceTarget"/>
****我在采用上面的测试程序进行测试的时候,发现确实在抛出异常之后,走到了增强之中,但是在增强代码结束之后,最终异常还是会被抛出。
4. 引介增强
引介增强和上面的增强都不太一样,可以理解为在运行时为一个类对象添加了新的功能,这将极大地改变我们编写代码时的思路。
这里添加一个新的接口,为性能监视类添加是否需要监控的功能。
public interface Monitorable { void setMonitorActivate(boolean active); }
这里是增强类
public class ControllablePerformanceMonitor extends DelegatingIntroductionInterceptor implements Monitorable { private ThreadLocal<Boolean> monitorStatusMap = new ThreadLocal<Boolean>(); public void setMonitorActivate(boolean active) { monitorStatusMap.set(active); } @Override public Object invoke(MethodInvocation mi) throws Throwable { Object obj = null; if (monitorStatusMap.get() != null && monitorStatusMap.get()) { PerformanceMonitor.begin(mi.getClass().getName() + "." + mi.getMethod().getName()); obj = super.invoke(mi); PerformanceMonitor.end(); } else { obj = super.invoke(mi); } return obj; } }
配置文件:
<bean id="pmonitor" class="com.firethewhole.maventest07.introduce.ControllablePerformanceMonitor"/> <bean id="forumServiceTarget" class="com.firethewhole.maventest07.introduce.ForumService"/> <bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean" p:interfaces="com.firethewhole.maventest07.introduce.Monitorable" p:target-ref="forumServiceTarget" p:interceptorNames="pmonitor" p:proxyTargetClass="true"/>
测试程序:
String configLocation = "com/firethewhole/maventest07/introduce/beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation); ForumService forumService = (ForumService) ctx.getBean("forumService"); forumService.removeForum(10); forumService.removeTopic(1022); Monitorable moniterable = (Monitorable) forumService; moniterable.setMonitorActivate(true); forumService.removeForum(20); forumService.removeTopic(1022);
输出:
模拟删除Forum记录:10
模拟删除Topic记录:1022
begin monitor...
模拟删除Forum记录:20
end monitor...
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.removeForum花费20毫秒。
begin monitor...
模拟删除Topic记录:1022
end monitor...
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.removeTopic花费20毫秒。
可以看到在更改可检测属性为true之后,增强才变的有效的。
- maventest07.zip (40.6 KB)
- 下载次数: 0
发表评论
-
Spring基础:数据访问(3)
2017-01-15 09:29 400在开源世界里,有很多ORM框架使用,比如Hibernate,还 ... -
Spring基础:数据访问(2)
2016-12-31 10:55 490上一篇主要将了Spring JDB ... -
Spring基础:数据访问(1)
2016-12-27 08:22 335Spring JDBC通过模板和回调机制大大降低了使用JDBC ... -
Spring基础:AOP编程(5)
2016-11-30 07:35 338基于Schema的AOP编程 基于AspectJ的AOP编程已 ... -
Spring基础:AOP编程(4)
2016-11-27 12:17 371基于AspectJ的AOP编程 AspectJ的切点函数非常 ... -
Spring基础:AOP编程(3)
2016-11-19 10:44 349基于切面的AOP编程 通过Advice,可以创建方法前,后, ... -
Spring基础:AOP编程(1)
2016-11-14 01:08 378Java编程中的代理 Spring以IoC为基础,发展了另外 ... -
Spring基础:IoC容器(2)
2016-11-12 10:00 398容器注入类型 最常见的注入类型是字面值注入,像String和 ... -
Spring基础:IoC容器(1)
2016-11-10 08:15 359在IoC容器中装配Bean 4.1.2.RELEASE版本的 ... -
Spring基础:稍显复杂的Spring Hello World
2016-11-01 00:59 358本文参考《Spring 3.x企业应用开发》这本书完成,作为自 ... -
使用Eclipse创建基于Maven Web工程
2016-06-06 19:19 408第一步:创建一个maven-webapp类型的工程 完 ...
相关推荐
NULL 博文链接:https://foreversky12.iteye.com/blog/2341332
NULL 博文链接:https://foreversky12.iteye.com/blog/2337737
NULL 博文链接:https://foreversky12.iteye.com/blog/2339065
NULL 博文链接:https://foreversky12.iteye.com/blog/2341705
Spring AOP面向方面编程原理:AOP概念,主要介绍面向对象的概念及原理,及作者的一些理解。
Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理
为了说明Spring的AOP原理,本人使用代理模式中的动态代理完成演示AOP编程的原理的演示。相信,如果你耐心看完整个程序(几乎一行注释一行代码),那么你对Spring这个东西就不是觉得有什么神秘了! 阅读对象:凡是喜爱...
spring AOP切面编程 运行环境:eclipse 构建工具:maven 不提供maven构建,maven用来解决jar包的依赖
小马哥讲 Spring AOP 编程思想 - API 线索图.pdf
aop写一个简单的计算器:(1)日志功能:在程序执行期间追踪正在发生的活动(打印出调用的方法,以及参数的参数值);...利用简单的实例来理解spring的aop编程,以aspectJ为例,理解环绕通知的真正含义。
package com.gc.aop下为:aop方式ProxyFactoryBean代理 package com.gc.aop下为:aop方式ProxyFactoryBean代理 package com.gc.autoproxy下为:aop方式自动代理 package com.gc.cglib下为:aop方式cglib代理 ...
学习Spring开发的AOP面向切面编程时所需要的jar包,包括com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供...
通过模拟SpringAOP,设置四个Advice实现简单的切面编程
spring aop 编程所需要的搜友JAR包
编程语言+JAVAspring+AOP编程+面向切面**:这是一个关于JAVAspring编程语言的AOP编程的面向切面的资源,适合有一定JAVAspring基础的开发者。它介绍了JAVAspring的AOP编程的概念、原理和作用,以及如何使用JAVAspring...
Spring中aop编程所需要的jar包,4个核心包,2个aop包,2个第三方依赖包
Spring,面向切面编程AOP例子!AOP(Aspect Oriented Programming)!
关于Spring的IOC和AOP的例子,帮助初学者入门。 内有bean的声明、注入;切入点和通知等功能例子。 环境配置:myeclipse, spring2.5