- 浏览: 15817 次
- 性别:
- 来自: 南京
文章分类
最新评论
Java编程中的代理
Spring以IoC为基础,发展了另外一个底层组件,就是AOP。
AOP的含义是“面向切面的编程”,将业务无关的代码但是又和业务缠在一起的代码剥离出去。AOP是一个很复杂的概念,这里只是拿出冰山一角说明一下。
AOP的术语
1.连接点(Joinpoint):程序执行的某一个特定的位置:比如类开始初始化前,初始化后,某个方法调用的前后,方法抛出异常的时候,等等具有某一种边界性质的特定点都可以称之为“连接点”。
2.切点(Pointcut):感兴趣的点的集合,如果说连接点是数据库中存储的数据的话,那切点就是where子句查询出来的目标点了。
3.增强(Advice):有的地方按照字面的意思翻译成通知,这里使用增强更加形象,即对目标对象的功能进行增强。
4.目标对象(Target):即待增强的对象。
5.引介(Introduction):特殊的增强,可以为类添加方法和属性。
6.织入(Weaver):织入就是以某种技术,将增强和目标对象融合起来,构建新类的过程,总结起来有3种织入技术。
Spring采用第三种代理织入,所以不需要额外的编译器。
7.代理(Proxy);织入增强之后的目标类生成的新的类。
8.切面(Advisor):由增强和切点组合形成。
现在来看一个带有横切逻辑的实例:
输出以下信息:
begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumService.Impl.removeForum花费20毫秒。
begin monitor...
模拟删除Topic记录:1012
end monitor...
com.firethewhole.maventest07.proxy.ForumService.Impl.removeTopic花费20毫秒。
这里性能代码和业务代码都在一起,将来修改业务代码的时候,性能监控代码可能也需要同时修改,显的很不清晰。
使用JDK动态代理技术
首先将性能横切代码都删除掉
在InvocationHandler中创建代理类,在调用ForumServiceAopStyleImpl的方法的时候,可以只能增强逻辑,先执行性能监控代码。接下来看下如何使用
输出结果:
begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl.removeForum花费47毫秒。
begin monitor...
模拟删除Topic记录:1012
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl.removeTopic花费31毫秒。
使用CGLib创建代理
使用JDK自带的InvocationHandler有一个局限性,就是只能针对接口进行代理,如果想直接针对类进行代理的话,就只能使用CGLib了。首先需要加入maven依赖。
基于CGLib创建代理类。
输出结果:
begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl$$EnhancerByCGLIB$$58fbcf09.removeForum花费125毫秒。
begin monitor...
模拟删除Topic记录:1023
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl$$EnhancerByCGLIB$$58fbcf09.removeTopic花费32毫秒。
可以看出CGLib创建出来的类的名字还是比较奇怪的,另外还有一点CGLib在创建对象的时候没有Invocation快,不适合需要反复创建对象的场合,在IoC容器启动的时候创建较为合适。
Spring以IoC为基础,发展了另外一个底层组件,就是AOP。
AOP的含义是“面向切面的编程”,将业务无关的代码但是又和业务缠在一起的代码剥离出去。AOP是一个很复杂的概念,这里只是拿出冰山一角说明一下。
AOP的术语
1.连接点(Joinpoint):程序执行的某一个特定的位置:比如类开始初始化前,初始化后,某个方法调用的前后,方法抛出异常的时候,等等具有某一种边界性质的特定点都可以称之为“连接点”。
2.切点(Pointcut):感兴趣的点的集合,如果说连接点是数据库中存储的数据的话,那切点就是where子句查询出来的目标点了。
3.增强(Advice):有的地方按照字面的意思翻译成通知,这里使用增强更加形象,即对目标对象的功能进行增强。
4.目标对象(Target):即待增强的对象。
5.引介(Introduction):特殊的增强,可以为类添加方法和属性。
6.织入(Weaver):织入就是以某种技术,将增强和目标对象融合起来,构建新类的过程,总结起来有3种织入技术。
- 编译期织入:需要特殊的Java编译器
- 类装载期织入:需要特殊的类装载器
- 动态代理织入:在运行期为目标类添加增强
Spring采用第三种代理织入,所以不需要额外的编译器。
7.代理(Proxy);织入增强之后的目标类生成的新的类。
8.切面(Advisor):由增强和切点组合形成。
现在来看一个带有横切逻辑的实例:
public class ForumServiceImpl implements ForumService { public void removeTopic(int topicId) { PerformanceMonitor.begin("com.firethewhole.maventest07.proxy.ForumService.Impl.removeTopic"); System.out.println("模拟删除Topic记录:" + topicId); try { Thread.currentThread().sleep(20); } catch (InterruptedException e) { throw new RuntimeException(e); } PerformanceMonitor.end(); } public void removeForum(int forumId) { PerformanceMonitor.begin("com.firethewhole.maventest07.proxy.ForumService.Impl.removeForum"); System.out.println("模拟删除Forum记录:" + forumId); try { Thread.currentThread().sleep(20); } catch (InterruptedException e) { throw new RuntimeException(e); } PerformanceMonitor.end(); } }
public class PerformanceMonitor { private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>(); public static void begin(String method) { System.out.println("begin monitor..."); MethodPerformance mp = new MethodPerformance(method); performanceRecord.set(mp); } public static void end() { System.out.println("end monitor..."); MethodPerformance mp = performanceRecord.get(); mp.printPerformance(); } }
public class MethodPerformance { private long begin; private long end; private String serviceMethod; public MethodPerformance(String serviceMethod) { this.serviceMethod = serviceMethod; this.begin = System.currentTimeMillis(); } public void printPerformance() { end = System.currentTimeMillis(); long elapse = end - begin; System.out.println(serviceMethod + "花费" + elapse + "毫秒。"); } }
ForumService forumService = new ForumServiceImpl(); forumService.removeForum(10); forumService.removeTopic(1012);
输出以下信息:
begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumService.Impl.removeForum花费20毫秒。
begin monitor...
模拟删除Topic记录:1012
end monitor...
com.firethewhole.maventest07.proxy.ForumService.Impl.removeTopic花费20毫秒。
这里性能代码和业务代码都在一起,将来修改业务代码的时候,性能监控代码可能也需要同时修改,显的很不清晰。
使用JDK动态代理技术
首先将性能横切代码都删除掉
public class ForumServiceAopStyleImpl implements ForumService { public void removeTopic(int topicId) { System.out.println("模拟删除Topic记录:" + topicId); try { Thread.currentThread().sleep(20); } catch (InterruptedException e) { throw new RuntimeException(e); } } public void removeForum(int forumId) { System.out.println("模拟删除Forum记录:" + forumId); try { Thread.currentThread().sleep(20); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
public class PerformanceHandler implements InvocationHandler { private Object target; public PerformanceHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PerformanceMonitor.begin(target.getClass().getName() + "." + method.getName()); Object obj = method.invoke(target, args); PerformanceMonitor.end(); return obj; } }
在InvocationHandler中创建代理类,在调用ForumServiceAopStyleImpl的方法的时候,可以只能增强逻辑,先执行性能监控代码。接下来看下如何使用
// 加入动态代理的方法 ForumService target = new ForumServiceAopStyleImpl(); PerformanceHandler handler = new PerformanceHandler(target); ForumService proxy = (ForumService) Proxy.newProxyInstance( target.getClass().getClassLoader() , target.getClass().getInterfaces() , handler); proxy.removeForum(10); proxy.removeTopic(1012);
输出结果:
begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl.removeForum花费47毫秒。
begin monitor...
模拟删除Topic记录:1012
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl.removeTopic花费31毫秒。
使用CGLib创建代理
使用JDK自带的InvocationHandler有一个局限性,就是只能针对接口进行代理,如果想直接针对类进行代理的话,就只能使用CGLib了。首先需要加入maven依赖。
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz) { enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { PerformanceMonitor.begin(obj.getClass().getName() + "." + method.getName()); Object result = proxy.invokeSuper(obj, args); PerformanceMonitor.end(); return result; } }
基于CGLib创建代理类。
// 使用Cglib代理 CglibProxy proxyCglib = new CglibProxy(); ForumServiceAopStyleImpl forumServiceImpl = (ForumServiceAopStyleImpl) proxyCglib.getProxy(ForumServiceAopStyleImpl.class); forumServiceImpl.removeForum(10); forumServiceImpl.removeTopic(1023);
输出结果:
begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl$$EnhancerByCGLIB$$58fbcf09.removeForum花费125毫秒。
begin monitor...
模拟删除Topic记录:1023
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl$$EnhancerByCGLIB$$58fbcf09.removeTopic花费32毫秒。
可以看出CGLib创建出来的类的名字还是比较奇怪的,另外还有一点CGLib在创建对象的时候没有Invocation快,不适合需要反复创建对象的场合,在IoC容器启动的时候创建较为合适。
- maventest07.zip (19.5 KB)
- 下载次数: 0
发表评论
-
Spring基础:数据访问(3)
2017-01-15 09:29 399在开源世界里,有很多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 370基于AspectJ的AOP编程 AspectJ的切点函数非常 ... -
Spring基础:AOP编程(3)
2016-11-19 10:44 349基于切面的AOP编程 通过Advice,可以创建方法前,后, ... -
Spring基础:AOP编程(2)
2016-11-15 23:40 361基于ProxyFactory的AOP编程 Spring只支持 ... -
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/2339065
NULL 博文链接:https://foreversky12.iteye.com/blog/2338186
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例子!AOP(Aspect Oriented Programming)!
Spring中aop编程所需要的jar包,4个核心包,2个aop包,2个第三方依赖包
关于Spring的IOC和AOP的例子,帮助初学者入门。 内有bean的声明、注入;切入点和通知等功能例子。 环境配置:myeclipse, spring2.5