JDK动态代理和CGLIB动态代理+源码下载

在上一篇文章-java代理详解讲解实现机制,一种是继承另外一种是组合,而且通过做实现也证明使用组合的方式更加的灵活。之后提到了代理的两种种类,一种是静态代理,另外一种是动态代理。上一篇文件中着重介绍的是静态代理(相对于动态代理很容易理解)。这一片文章就接着介绍动态代理。

动态代理实现的最终效果:通过以一个统一的方式实现对任意的接口/类的代理。相比较静态代理而言,我们可以不用再无限制的增加代理类,不用再写许多重复的代码。很符合面向对象设计原则中的"开闭原则":对修改关闭,对扩展开放。

动态代理有很多的实现,我们比较熟悉的就是JDK动态代理和CGLIB的动态代理,这种两技术也是spring实现AOP的使用的重要技术。

1. JDK动态代理

JDK底层封装了Proxy和InvocationHandler实现了对任意接口的代理。他们各自有自己的任务,Proxy主要负责动态生成代理类;InvocationHandler主要负责灵活指定代理内容。

1.1 动态生成代理类

想要实现“通过一个统一的方式方式对任意接口的代理”,使用的方式就是将接口以参数的形式传递到创建代理类的方法中。在JDK中负责创建代理类的类就是Proxy,他提供了两个方法创建代理,分别是newProxyInstance()和getProxyClass()。下面是JDK帮助文档中对他们的介绍:

Proxy Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

关于Proxy的相关介绍

从帮助文档中可以看出JDK给我们提供了两种创建代理类的方式,代码如下

package cn.jdk.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import cn.jdk.dynamicproxy.Service;

public class Main {

	public static void main(String[] args) throws Throwable {
//		jdk动态代理==第一种创建方式--newProxyInstance()
		Object proxy = Proxy.newProxyInstance(
				ServiceImpl.class.getClassLoader(),
				ServiceImpl.class.getInterfaces(),
				new ServiceInvocationHandler(new ServiceImpl()));
		Service service1 = (Service)proxy;
		service1.add();

		//jdk和cglib两种动态代理都不能够代理final类型的方法

//		jdk动态代理==第二种创建方式--getProxyClass()
		Class<?> proxyClass = Proxy.getProxyClass(
				ServiceImpl.class.getClassLoader(),
				ServiceImpl.class.getInterfaces());

		Object serviceProxy = proxyClass.getConstructor(new Class[]{InvocationHandler.class})
		      .newInstance(new ServiceInvocationHandler(new ServiceImpl()));
		Service service2 = (Service)serviceProxy;
		service2.add();
	}
}
package cn.jdk.dynamicproxy;

public interface Service {
	public void add();
}
package cn.jdk.dynamicproxy;

/**
 *
* 类名称:ServiceImpl
* 类描述: 委托类
* 修改人:pangfan
*
 */
public class ServiceImpl implements Service{
	public void add() {
		System.out.println("向数据库中添加数据!");
	}
}

这是创建代理类的代码,但不是完整的还加上下面的灵活指定代理内容。

2.2 灵活指定代理内容

代理内容:在上一篇文章我们曾经介绍过"代理模式",那个里面提到代理类是需要对委托类进行预处理,过滤消息,把消息转发给委托类,以及事后处理消息。而这些预消息,过滤消息,把消息转发给委托类,以及事后处理消息就是代理内容。

比如对于事务代理而言,在执行委托类的方法之前,开启事务就是代理内容;方法执行之后,关闭事务也是代理内容。

灵活指定:由用户决定代理内容是什么!

下面就将代码补全,看一下执行效果。

package cn.jdk.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ServiceInvocationHandler implements InvocationHandler {
	private Object obj;
	public ServiceInvocationHandler(Service service) {
		super();
		this.obj = service;
	}
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		 Object result=null;
		System.out.println("jdk动态代理--开始事务");
		result = method.invoke(obj,args);
		System.out.println("jdk动态代理--结束事务 "+"\r\n");
		return result;
	}
}

执行效果展示:

最后用一张UML图将上面的所有东西做一个总结。

2. CGLIB动态代理

上面的指能够动态生成接口的代理类,如果是一个类就不能够动态生成。而cglib能够动态生成类的代理类,这个类可以不用实现接口

实现原理基本上是一样的,应用也是基本上一样的。

需要引用的jar包:cglib-nodep-2.2.2.jar 和 com.springsource.org.objectweb.asm-3.2.0.jar

直接上代码:

package cn.cglib.dynamicproxy;

import net.sf.cglib.proxy.Enhancer;

public class Main {

	public static void main(String[] args) {
//		cglib动态代理
		Monkey monkey = (Monkey)Enhancer.create(
				Monkey.class,
				new MonkeyInvocationHandler());
		monkey.eat();
//		final方法不能够被代理
		monkey.type();
	}
}
package cn.cglib.dynamicproxy;

public class Monkey {

	public void eat(){
		System.out.println("吃香蕉!");
	}
	//final方法,测试是否能够代理此方法
	public final String type(){
		return "金丝猴";
	}
}
package cn.cglib.dynamicproxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class MonkeyInvocationHandler
		implements MethodInterceptor {
	public Object intercept(Object proxy, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		 Object result=null;
		System.out.println("cglib动态代理--开始事务");
		result = methodProxy.invokeSuper(proxy,args);
		System.out.println("cglib动态代理--结束事务");
		return result;
	}
}

源码下载地址:jdk和cglib实现动态代理

时间: 2024-12-28 00:36:57

JDK动态代理和CGLIB动态代理+源码下载的相关文章

jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)

代理模式是一种很常见的模式,关于底层原理网上看到很多的有关的讲解,但看了一些都觉得比较粗略,很多时候把底层代码copy下来也不大讲解,感觉不如自己详细的写上一篇.本文将以非常详细的说明来分析cglib动态代理底层的实现原理,篇幅较长,但是每个核心方法代码中每步都有说明.还请耐心阅读 1. 举例 使用cglib代理需要引入两个包,maven的话包引入如下 <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency&

深入探索spring技术内幕(六): JDK动态代理和cglib生成代理

[ JDK生成代理 ] JDK中给我们提供了一个Proxy类可以动态的给我们生成代理. 假定我们要做一个权限管理系统, 需要控制用户对某一个方法的访问. 如果user为null, 那么不让用户访问save方法. ① 接口类: PersonService public interface PersonService { public void save(); } ② 实现类: PersonServiceImpl public class PersonServiceImpl implements P

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

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

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

Spring的两大特性是IOC和AOPIOC负责将对象动态的注入到容器,从而达到一种需要谁就注入谁,什么时候需要就什么时候注入的效果.理解spring的ioc也很重要.但是今天主要来和大家讲讲aop.AOP 广泛应用于处理一些具有横切性质的系统级服务,AOP 的出现是对 OOP 的良好补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等等. AOP实现的关键在于AOP框架自动创建的AOP代理.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) 动态代理 我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方

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

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

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

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

jdk动态代理和cglib动态代理的区别

CGLIB代理: CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类. CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的. 如果目标对象实现了接口,可以强制使用CGLIB实现代理. 如果目标对象没有实现接口,则默认会采用CGLIB代理: 为什么jdk动态代理必须基于接口 原因如下: 1.生成的代理类继承了Proxy,由于java是单继承,所以只能实现接口,通过接口

spring源码学习【准备】之jdk动态代理和cglib动态代理的区别和性能

一:区别:---->JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了.--->JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理. 性能:--->jdk的动态代理由于jdk版本的升级,渐渐超越cglib 二:都说 Cglib 创建的动态代理的