`

JDK、CGLib动态代理

    博客分类:
  • AOP
阅读更多

  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 框架中 JDK 动态代理和 CGLIB 动态代理是 Spring AOP 中一个非常重要的知识点。Spring AOP 框架会根据实际情况选择使用 JDK 的动态代理还是 CGLIB 的动态代理。 JDK 动态代理是 Java 自带的动态代理机制,它...

    浅谈JDK动态代理与CGLIB代理去区别

    本篇文章将深入探讨JDK动态代理和CGLIB代理的区别,以及它们在实际应用中的选择。 首先,JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类用于创建一个代理对象...

    Jdk动态代理和cglib动态代理原理

    - **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成的子类,而JDK代理需要反射调用接口方法。 在实际开发中,如Spring AOP框架就同时支持JDK和...

    AOP之JDK动态代理和CGLib动态代理

    Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...

    jdk和cglib动态代理的例子{jar包+源码}

    jdk和cglib动态代理的例子{jar包+源码} 解压:如有问题 用快压

    jdk与cglib动态代理与底层实现

    - **CGLIB代理**:CGLIB通过ASM生成一个继承自目标类的新类,这个新类覆盖了目标类的所有方法,并在这些方法内部调用拦截器链。在运行时,这个新类的实例作为代理对象。 5. **优缺点**: - JDK代理简单易用,但...

    java代理机制 JDK动态代理和cglib代理 详解

    本文将深入探讨两种主要的Java代理实现:JDK动态代理和CGLIB代理。 一、JDK动态代理 JDK动态代理基于接口实现,它要求被代理的类必须实现至少一个接口。在运行时,Java会动态地创建一个新的类,这个类实现了与原始...

    Jdk动态代理,cglib动态代理,反射和拦截器(链)示例

    本资源提供的示例涵盖了这些核心概念,通过JDK动态代理、CGLIB动态代理以及拦截器链的实践,帮助开发者深入理解并掌握这些技术。 首先,让我们来探讨JDK动态代理。Java标准库中的`java.lang.reflect.Proxy`类和`...

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理) Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解...

    jdk 的动态代理和CGLIB代理

    jdk 的动态代理和CGLIB代理

    JDK动态代理和CGLIB代理

    JDK动态代理和CGLIB代理是两种常用的实现方式。 首先,我们来看看JDK动态代理。JDK动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象...

    jdk动态代理和CGlib动态代理

    JDK动态代理和CGlib动态代理是Java中实现这一目标的两种主要方式。 ### JDK动态代理 JDK动态代理基于Java的接口实现。如果一个类实现了至少一个接口,我们就可以为这个类创建一个动态代理。动态代理通过`java.lang....

    JDK动态代理和Cglib动态代理实例源码

    本篇将详细探讨JDK动态代理和Cglib动态代理,并通过源码实例来加深理解。 首先,JDK动态代理是Java内置的一种机制,它依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类...

    CGlib实现动态代理(承接上面JDK实现动态代理)

    与JDK的动态代理不同,JDK代理基于接口,如果目标类没有实现接口,就无法使用JDK的动态代理。而CGlib则无需目标类实现任何接口,因此它的应用范围更广。 以下是使用CGlib实现动态代理的关键步骤: 1. 引入依赖:在...

    输出JDK和CGLib动态代理产生的class文件.zip

    2. CGLib代理项目: - src/main/java:包含目标类 - target/classes:编译后的class文件,包括目标类的class文件,以及由CGLib生成的子类class文件 - 测试代码:展示如何使用Enhancer创建代理对象并调用方法 这...

    静态代理、jdk动态代理、cglib动态代理

    Cglib 动态代理的实现方式是:我们首先需要定义一个类,然后使用 Cglib 库来生成该类的代理对象,该代理对象将拦截对被代理对象的所有方法调用,并控制对被代理对象的访问。 Cglib 动态代理的优点是:它的实现方式...

    JDK和CGlib分别实现的动态代理源代码

    JDK和CGlib是两种常用的动态代理实现方式,它们各自有不同的特性和使用场景。 首先,我们来详细了解一下JDK动态代理。JDK动态代理基于接口实现,它要求被代理的对象必须实现至少一个接口。通过`java.lang.reflect....

    代理模式-静态动态代理-jdk动态代理-cglib动态代理

    在Java中,代理模式有多种实现方式,包括静态代理、JDK动态代理和CGLIB动态代理。 **静态代理** 静态代理是最早也是最基础的代理实现方式。在静态代理中,我们需要创建一个代理类,这个代理类与原始类(被代理类)...

    CGLIB 和 JDK生成动态代理类的区别

    CGLIB和JDK动态代理是两种常用的实现方式,它们各有优缺点,适用于不同的场景。下面将详细探讨这两种动态代理的区别。 首先,JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect....

    JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)

    Java提供了两种主要的动态代理实现方式:JDK动态代理和CGLIB动态代理。 **JDK动态代理**: JDK动态代理基于接口实现,也就是说,被代理的对象必须实现至少一个接口。代理机制的核心是`java.lang.reflect.Proxy`类和...

Global site tag (gtag.js) - Google Analytics