Java进阶之 JDK动态代理与Cglib动态代理

一、动态代理概述:

与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式【Proxy Pattern】),

动态代理类的字节码是在程序运行时由Java反射机制动态生成。

注意:

1、AspectJ是采用编译时生成AOP代理类,具有更好的性能,但是需要使用特定的编译器进行处理

2、Spring AOP采用运行时生成AOP代理类,无需使用特定编译器进行处理,但是性能相对于AspectJ较差

二、JDK动态代理 [对有实现接口的对象做代理]

1、JDK动态代理中 需要了解的两个重要的类或接口 [InvocationHandler 和 Proxy]

① InvocationHandler接口

public interface InvocationHandler {
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
} 

参数说明:

Object proxy:指被代理的对象

Method method:我们所要调用被代理对象的某个方法的Method对象

Object[] args:被代理对象某个方法调用时所需要的参数

可以将InvocationHandler接口的子类想象成一个代理的最终操作类。

说明:每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类(Proxy)的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke
方法来进行调用。同时在invoke的方法里 我们可以对被代理对象的方法调用做增强处理(如添加事务、日志、权限验证等操作)。

② Proxy类

Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,该类常用的调用方法如下:

newProxyInstance方法参数说明如下:

ClassLoader loader:类加载器,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

Class<?>[] interfaces:得到被代理类全部的接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口,这样我就能调用这组接口中的方法了

InvocationHandler h:得到InvocationHandler接口的子类实例

2、JDK动态代理代码示例:

首先我们定义了一个Subject类型的接口:Subject.java

public interface Subject {
    public void visit();
}

接着定义一个接口的实现类,这个类就是我们示例中的被代理对象:RealSubject.java

/**
 * 被代理类
 * @author [email protected]
 *
 */
public class RealSubject implements Subject {

	@Override
	public void visit() {
	     System.out.println("I am 'RealSubject',I am the execution method");
	}

}

第三步 定义一个动态代理类(必须要实现 InvocationHandler 这个接口):DynamicProxy.java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * JDK动态代理类
 * @author [email protected]
 *
 */
public class DynamicProxy implements InvocationHandler {

	// 我们要代理的真实对象(委托对象)
	private Object subject;

	// 构造方法,给我们要代理的真实对象赋初值
	public DynamicProxy(Object obj){
		this.subject = obj;
	}

	@Override
	public Object invoke(Object object, Method method, Object[] args)
			throws Throwable {
		// 在代理真实对象操作前 我们可以添加一些自己的操作
		System.out.println("before proxy invoke");

		// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
		method.invoke(subject, args);

		// 在代理真实对象操作后 我们也可以添加一些自己的操作
		System.out.println("after proxy invoke");
		return null;
	}

}

最后代理测试类:Client.java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client {

	public static void main(String[] args) {
		// 我们要代理的真实对象
		Subject realSubject = new RealSubject();
		// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象调用方法的
		InvocationHandler handler = new DynamicProxy(realSubject);
		/*
		 * 通过Proxy的newProxyInstance方法来动态创建我们的代理对象,我们来看看其三个参数<br/>
		 * 参数一:我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象<br/>
		 * 参数二:我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了<br/>
		 * 参数三:我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
		 */
		Subject proxyInstance = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(),
				RealSubject.class.getInterfaces(),
				handler);

		System.out.println(proxyInstance.getClass().getName());
		proxyInstance.visit();

	}

}

运行->控制台输出结果如下:

com.sun.proxy.$Proxy0
before proxy invoke
I am 'RealSubject',I am the execution method
after proxy invoke

三、Cglib(Code Generation Library)动态代理 [对没有实现接口的普通类做代理]

1、概述:

Cglib是一个优秀的动态代理框架,它的底层使用ASM(JAVA字节码处理框架)在内存中动态的生成被代理类的子类。使用CGLIB即使被代理类没有实现任何接口也可以实现动态代理功能。但是不能对final修饰的类进行代理。

2、原理:

通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用。

<JDK动态代理与CGLib动态代理均是实现Spring AOP的基础>

3、使用:

使用Cglib前需要导入以下两个jar文件:

asm.jar – Cglib的底层实现。

【cglib包的底层是使用字节码处理框架ASM来转换字节码并生成新的类,所以cglib包要依赖于asm包】

cglib.jar - Cglib的核心jar包。

4、Cglib动态代理代码示例:

首先定义一个没有实现接口的代理委托类:CglibRealSubject.java

/**
 * 没有实现接口的代理委托类
 * @author [email protected]
 *
 */
public class CglibRealSubject{

	public void visit() {
		System.out.println("I am 'RealSubject',I am the execution method");
	}

}

接着定义一个Cglib动态代理类: CglibDynamicProxy.java

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
 * 使用cglib动态代理
 * @author [email protected]
 *
 */
public class CglibDynamicProxy implements MethodInterceptor {

	private Object target;

	/**
	 * 创建代理对象
	 * @param target 被代理的对象
	 * @return
	 */
	public Object getProxyInstance(Object target){
		this.target = target;
		// 声明增强类实例
		Enhancer enhancer = new Enhancer();
		// 设置被代理类字节码,CGLIB根据字节码生成被代理类的子类
                enhancer.setSuperclass(this.target.getClass());
                // 设置要代理的拦截器,回调函数,即一个方法拦截   new MethodInterceptor()
                enhancer.setCallback(this);
                // 创建代理对象 实例
                return enhancer.create();
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		// 在代理真实对象操作前 我们可以添加一些自己的操作
		System.out.println("前置代理,增强处理");

		proxy.invokeSuper(obj, args);

		// 在代理真实对象操作后 我们也可以添加一些自己的操作
		System.out.println("后置代理,增强处理");
		return null;
	}

}

最后测试客户端类:CglibClient.java

public class CglibClient {

	public static void main(String[] args) {
		CglibDynamicProxy cglib = new CglibDynamicProxy();
		CglibRealSubject realSubject = (CglibRealSubject) cglib.getProxyInstance(new CglibRealSubject());
		realSubject.visit();
	}

}

运行->控制台输出结果如下:

前置代理,增强处理
I am 'RealSubject',I am the execution method
后置代理,增强处理

四、扩展学习

关于什么是AOP思想?Spring AOP实现原理?及什么样的系统业务场景我们可以使用到AOP这种动态代理技术?

小吕推荐一篇非常值得阅读和学习的文章: Spring AOP实现原理与CGLIB应用

—————————————————————————————————————

如果文章内容对您有帮助, 不要忘记 顶 一下,来支持一下哦!

如果您对文章内容有任何疑问或有更好的见解, 可以通过评论留言或发邮件的方式联系我:

[email protected]

如果需要转载,请注明出处,谢谢!!

—————————————————————————————————————

时间: 2024-08-02 06:59:41

Java进阶之 JDK动态代理与Cglib动态代理的相关文章

Java学习之:JDK动态代理与CGLIB动态代理

代理的概念:简单的理解就是通过为某一个对象创建一个代理对象,我们不直接引用原本的对象,而是由创建的代理对象来控制对原对象的引用. 动态代理:是指在程序运行时由Java反射机制动态生成,无需手动编写代码.动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类. 代理原理:代理对象内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象.同时,代理对象可以在执行真实对象操作时,附加其他的操作

Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法.如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱.所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户.而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品. 专业点说:代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象

JDK动态代理和CGLIB动态代理

转载自http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html 静态代理 静态代理相对来说比较简单,无非就是聚合+多态: 参考:设计模式笔记 – Proxy 代理模式 (Design Pattern) 动态代理 我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方

代理模式 &amp; Java原生动态代理技术 &amp; CGLib动态代理技术

第一部分.代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.(其实就是在代理类中关联一个委托类的实例,然后在代理类中进行包装). UML图如下: 第二部分.在Java中实现代理模式  按照代理的创建时期,代理类可以分

关于JDK动态代理和CGLIB动态代理

1. 代理模式 一句话总结:为其他对象提供一种代理以控制对这个对象的访问.千篇一律的介绍:代理模式是常用的java设计模式,他的特征是代理类与委托类(或目标类)有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具

JDK动态代理与Cglib动态代理(转载)

spring容器通过动态代理再结合java反射思想可以使得方法调用更加简洁 一.动态代理概述: 与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式[Proxy Pattern](博主), 动态代理类的字节码是在程序运行时由Java反射机制动态生成. 注意:       1.AspectJ是采用编译时生成AOP代理类,具有更好的性能,但是需要使用特定的编译器进行处理 2.Spring AOP采用运行时生成AOP代理类,无需使用特定编译器进行处理,但是性能相对于Aspe

【Spring】AOP之JDK动态代理和CGLib动态代理

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 一.JAVA动态代理  1.1 代理模式         代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创

Spring 静态代理+JDK动态代理和CGLIB动态代理

代理分为两种:静态代理 动态代理 静态代理:本质上会在硬盘上创建一个真正的物理类 动态代理:本质上是在内存中构建出一个类. 如果多个类需要进行方法增强,静态代理则需要创建多个物理类,占用磁盘空间.而动态代理则是在内存中创建,不会对磁盘进行影响. 静态代理和JDK动态代理需要有接口. CGLIB动态代理无需有接口的情况下进行代理.实质:内存中构建出了目标类型的子类. JDK动态代理是JDK提供的,CGLIB动态代理是Spring提供的. 代理模式的三个组件:抽象主题 真实主题 代理主题 静态代理:

spring aop原理 JDK动态代理和CGLIB动态代理

Spring的两大特性是IOC和AOPIOC负责将对象动态的注入到容器,从而达到一种需要谁就注入谁,什么时候需要就什么时候注入的效果.理解spring的ioc也很重要.但是今天主要来和大家讲讲aop.AOP 广泛应用于处理一些具有横切性质的系统级服务,AOP 的出现是对 OOP 的良好补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等等. AOP实现的关键在于AOP框架自动创建的AOP代理.AOP代理主要分为静态代理和动态代理, 静态代理的代表为AspectJ:动态代理则