AOP,久违了!
在AOP概念理解里面呢,学习了一下AOP的一些使用场合,这一篇呢,就来真正写一些示例,来学习这样的一个概念。
在Spring AOP中呢,使用了动态代理技术在运行期织入增强的代码,我们都知道,JDK动态代理只提供了针对接口的代理,CGLib是对其的强有力补充,Spring AOP支持这两种代理方式。
先来看一个一般的带有AOP概念色彩的示例程序,然后再在这个程序的基础上,使用上JDK动态代理技术和CGlib代理技术。
1)
public class MethodPerformance {
private static final Log log = LogFactory.getLog(MethodPerformance.class);
private long begin;
private long end;
private String serviceMethod;//执行的方法
public MethodPerformance(String serviceMethod){
this.serviceMethod = serviceMethod;
this.begin = System.currentTimeMillis();
}
public void printPerformance(){
this.end = System.currentTimeMillis();
log.info(serviceMethod+" processing take "+(end-begin)+" millisecond.");//方法执行的耗时
}
}
这个类完成的功能是这样的,就是来监测一个类中方法的执行耗时。这样一来,可以有效的监测程序的执行耗时,从而为程序的运行速度做一些参考。
PerformanceMonitoring这个类呢,是对当前线程中运行的方法进行一个监测,实际上它充当了MethodPerformance的包装器了,begin方法接受执行的方法名,并记录方法执行的起始时间,end方法记录该方法的执行耗时,程序和逻辑都是相当的简单明了,现代码如下:
public class PerformanceMonitoring {
private static final Log log = LogFactory.getLog(PerformanceMonitoring.class);
private static ThreadLocal<MethodPerformance> performanceRecord =
new ThreadLocal<MethodPerformance>();//当前线程中
public static void begin(String method){
log.info("begin monitoring...");
MethodPerformance mp = new MethodPerformance(method);
performanceRecord.set(mp);
}
public static void end(){
log.info("end monitoring...");
MethodPerformance mp = performanceRecord.get();//获取当前线程的对象实例
mp.printPerformance();
}
}
现看一个service类,看看如何在方法中使用监测耗时,代码如下:
public class AopStudyService extends TestCase{
private static final AopStudyService instance = new AopStudyService();
public static AopStudyService getInstance(){
return instance;
}
public void analogRemoveInfo() throws InterruptedException{
PerformanceMonitoring.begin("analogRemoveInfo");//性能监测
Thread.currentThread().sleep(200);//模拟该方法执行了200毫秒
PerformanceMonitoring.end();//结束性能监测
}
public void testAnalogRemoveInfo() throws InterruptedException{
instance.analogRemoveInfo();
}
}
analogRemoveInfo方法,模拟了一个耗时200ms的删除操作,通过PerformanceMonitoring.begin("analogRemoveInfo")来启动监测起始方法,方法执行完毕后,再调用PerformanceMonitoring.end()来结束监测,最后我们用JUnit Test运行,结果输出如下:
2010-11-21 21:11:21 org.aopStudy.common.PerformanceMonitoring begin
信息: begin monitoring...
2010-11-21 21:11:22 org.aopStudy.common.PerformanceMonitoring end
信息: end monitoring...
2010-11-21 21:11:22 org.aopStudy.common.MethodPerformance printPerformance
信息: analogRemoveInfo processing take 203 millisecond.
通过这个例子,我想你肯定会对aop有一个感性的认识,但是这个程序有一个问题,我现在service里只有一个方法,如果service里的方法多了,那岂不是每个方法的执行开始之前我都要加入begin方法,方法执行完毕后调用end方法,这真的是件糟糕的事情,这无形中添加了我们写程序的负担,在编写复杂业务程序的时候,还得时刻提醒自己不忘记添加这两个方法,所以,必须改正它。
2)通过JDK的反射机制重新实现这个逻辑代码如下:
public class PerformaceHandler implements InvocationHandler {
private Object target;
public PerformaceHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
PerformanceMonitoring.begin(target.getClass().getName()+"."+method.getName());
Object obj = method.invoke(target, args);//通过反射调用方法
PerformanceMonitoring.end();
return obj;
}
}
这是个代理实例调用处理程序的一个典型使用方式,通过指定一个目标对象,然后通过代理实例调用方法时,将其指派到它的调用处理程序的 invoke
方法。invoke方法在通过反射调用方法的前后添加了如上的监测代码,现来看看目标对象
public class JdkReflectService extends TestCase implements IJdkReflectService{
private static final JdkReflectService instance = new JdkReflectService();
public static JdkReflectService getInstance(){
return instance;
}
public void analogRemoveInfo() throws InterruptedException{
// PerformanceMonitoring.begin("analogRemoveInfo");//性能监测
Thread.currentThread().sleep(200);//模拟该方法执行了200毫秒
// PerformanceMonitoring.end();//结束性能监测
}
public void testAnalogRemoveInfo() throws InterruptedException{
IJdkReflectService target = JdkReflectService.getInstance();
PerformaceHandler handler = new PerformaceHandler(target);
IJdkReflectService proxy = (IJdkReflectService) Proxy.newProxyInstance(
target.getClass().getClassLoader(), target.getClass()
.getInterfaces(), handler);
proxy.analogRemoveInfo();
}
}
可以看到在analogRemoveInfo() 方法中注释掉了如上的性能监测代码,通过JUnit Test运行可得到如上的结果。我们说过,JDK的代理是针对接口的,也就是说,即便像我们这个service中只有一个方法,为了使用JDK动态代理,我们还不得不多写一个service的接口,这下悲剧了,我们不禁会想:何必把简单的事情搞复杂呢?!OK,CGLib派上用场了:
3)
public class CglibProxy extends TestCase implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clz){
enhancer.setSuperclass(clz);//设置需要创建子类的类
enhancer.setCallback(this);
return enhancer.create();//返回创建的子类对象
}
/**
* 拦截所有目录类方法
* @param arg0 目录类实例
* @param arg1 目标类方法的反射对象
* @param arg2 方法参数
* @param arg3 代理实例
* */
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
PerformanceMonitoring.begin(arg0.getClass().getName()+"."+arg1.getName());
Object result = arg3.invokeSuper(arg0, arg2);
PerformanceMonitoring.end();
return result;
}
public void testCglibProxy() throws InterruptedException{
CglibProxy proxy = new CglibProxy();
CglibReflectService service = (CglibReflectService) proxy.getProxy(CglibReflectService.class);
service.analogRemoveInfo();
}
}
可以看到,通过实现MethodInterceptor接口的唯一方法intercept,在intercept这个方法里加入耗时监测,通过getProxy方法获取代理实例,再调用对应的方法即可,具体的代码可参见附件,也请各位多多指正,共同进步。
分享到:
相关推荐
Spring 框架中 JDK 动态代理和 CGLIB 动态代理是 Spring AOP 中一个非常重要的知识点。Spring AOP 框架会根据实际情况选择使用 JDK 的动态代理还是 CGLIB 的动态代理。 JDK 动态代理是 Java 自带的动态代理机制,它...
本篇文章将深入探讨JDK动态代理和CGLIB代理的区别,以及它们在实际应用中的选择。 首先,JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类用于创建一个代理对象...
- **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成的子类,而JDK代理需要反射调用接口方法。 在实际开发中,如Spring AOP框架就同时支持JDK和...
Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...
jdk和cglib动态代理的例子{jar包+源码} 解压:如有问题 用快压
- **CGLIB代理**:CGLIB通过ASM生成一个继承自目标类的新类,这个新类覆盖了目标类的所有方法,并在这些方法内部调用拦截器链。在运行时,这个新类的实例作为代理对象。 5. **优缺点**: - JDK代理简单易用,但...
本文将深入探讨两种主要的Java代理实现:JDK动态代理和CGLIB代理。 一、JDK动态代理 JDK动态代理基于接口实现,它要求被代理的类必须实现至少一个接口。在运行时,Java会动态地创建一个新的类,这个类实现了与原始...
本资源提供的示例涵盖了这些核心概念,通过JDK动态代理、CGLIB动态代理以及拦截器链的实践,帮助开发者深入理解并掌握这些技术。 首先,让我们来探讨JDK动态代理。Java标准库中的`java.lang.reflect.Proxy`类和`...
Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理) Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解...
jdk 的动态代理和CGLIB代理
JDK动态代理和CGLIB代理是两种常用的实现方式。 首先,我们来看看JDK动态代理。JDK动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象...
JDK动态代理和CGlib动态代理是Java中实现这一目标的两种主要方式。 ### JDK动态代理 JDK动态代理基于Java的接口实现。如果一个类实现了至少一个接口,我们就可以为这个类创建一个动态代理。动态代理通过`java.lang....
本篇将详细探讨JDK动态代理和Cglib动态代理,并通过源码实例来加深理解。 首先,JDK动态代理是Java内置的一种机制,它依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类...
与JDK的动态代理不同,JDK代理基于接口,如果目标类没有实现接口,就无法使用JDK的动态代理。而CGlib则无需目标类实现任何接口,因此它的应用范围更广。 以下是使用CGlib实现动态代理的关键步骤: 1. 引入依赖:在...
2. CGLib代理项目: - src/main/java:包含目标类 - target/classes:编译后的class文件,包括目标类的class文件,以及由CGLib生成的子类class文件 - 测试代码:展示如何使用Enhancer创建代理对象并调用方法 这...
Cglib 动态代理的实现方式是:我们首先需要定义一个类,然后使用 Cglib 库来生成该类的代理对象,该代理对象将拦截对被代理对象的所有方法调用,并控制对被代理对象的访问。 Cglib 动态代理的优点是:它的实现方式...
JDK和CGlib是两种常用的动态代理实现方式,它们各自有不同的特性和使用场景。 首先,我们来详细了解一下JDK动态代理。JDK动态代理基于接口实现,它要求被代理的对象必须实现至少一个接口。通过`java.lang.reflect....
在Java中,代理模式有多种实现方式,包括静态代理、JDK动态代理和CGLIB动态代理。 **静态代理** 静态代理是最早也是最基础的代理实现方式。在静态代理中,我们需要创建一个代理类,这个代理类与原始类(被代理类)...
CGLIB和JDK动态代理是两种常用的实现方式,它们各有优缺点,适用于不同的场景。下面将详细探讨这两种动态代理的区别。 首先,JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect....
Java提供了两种主要的动态代理实现方式:JDK动态代理和CGLIB动态代理。 **JDK动态代理**: JDK动态代理基于接口实现,也就是说,被代理的对象必须实现至少一个接口。代理机制的核心是`java.lang.reflect.Proxy`类和...