1.JAVA的动态代理特征:特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
它是在运行是生成的class对象,在生成时必须提供一组或一个interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当做这些interface中的任何一个来用,当然,这个DynamicProxy其实就是一个Proxy,他不会替你做实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。因此,DynamicProxy必须实现InvocationHandler接口。
5) 一个动态代理了和一个InvocationHandler 实现关联的。每一个动态代理实例的调用都要通过InvocationHandler接口的handler(调用处理器)来调用,动态代理不做任何执行操作,只是在创建动态代理时,把要实现的接口和handler关联,动态代理要帮助被代理执行的任务,要转交给handler来执行。其实就是调用invoke方法
动态代理:在程序运行时,运用反射机制动态创建而成
2.实用动态代理步骤:
A. 创建一个实现接口InvocationHandler的类,他必须实现invoke方法
B. 创建被代理的类以及接口。
C. 通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)创建一个代理
D. 通过代理调用方法
3.jdk动态代理例子:
文件列表:
业务接口:UserService
业务实现:UserServiceImpl
代理类的调用Handler实现:ProxyHandler
JUnit测试类:SpringProxyTest
package com.niewj.service;
import com.niewj.model.User;
public class UserServiceImpl implements UserService {
@Override
public void add(User user) {
System.out.println("User Saved. & ");
}
@Override
public void delete(User user) {
System.out.println("User Deleted. &");
}
}
package com.niewj.service;
import com.niewj.model.User;
public class UserServiceImpl implements UserService {
@Override
public void add(User user) {
System.out.println("User Saved. & ");
}
@Override
public void delete(User user) {
System.out.println("User Deleted. &");
}
}
package com.niewj.service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* JDK动态代理模拟
*
* 1.首先明确什么是目标对象target,什么是代理对象proxy!!
*
* 2.每个代理对象对象都会有一个相关的InvocationHandler对象。
* 当代理对象生成的时候,是创建的代理对象,
* 拿着相关的这个InvocationHandler对象,去自动调Handler类中实现的invoke方法的。
* 下面一段话来自@javadoc@
* <p>Each proxy instance has an associated invocation handler.
* When a method is invoked on a proxy instance, the method
* invocation is encoded and dispatched to the <code>invoke</code>
* method of its invocation handler.
*
* 3.还有就是我发现,我的Eclipse控制台TMD输出的顺序有误,害的老以为我人品出了什么问题,
* 不知道控制台的信息是不是不是栈式输出的。(好绕口)
*
*/
public class ProxyHandler implements InvocationHandler {
// 就是要给这个目标类创建代理对象。
private Object target;
// 传递代理目标的实例,因为代理处理器需要。也可以用set等方法。
public ProxyHandler(Object target) {
this.target = target;
}
/*
* 这个方法是给代理对象调用的。
* 留心的是内部的method调用的对象是目标对象,可别写错。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object ret = null;
// 1.调用前
cutIntoBefore(method.getName());
ret = method.invoke(target, args);
// 2.调用后
cutIntoAfter(method.getName());
return ret;
}
public void cutIntoBefore(String mName) {
System.err.println("调用____" + mName + "()____方法之前");
}
public void cutIntoAfter(String mName) {
System.err.println("调用____" + mName + "()____方法完后");
}
}
package com.niewj;
import java.lang.reflect.Proxy;
import org.junit.Test;
import com.niewj.model.User;
import com.niewj.service.ProxyHandler;
import com.niewj.service.UserService;
import com.niewj.service.UserServiceImpl;
public class SpringProxyTest {
@Test
@SuppressWarnings("rawtypes")
public void testJDKDynamicProxy() {
/* 1.获取UserServiceImpl对象--目标对象--也就是需要被代理的对象。 */
UserService userService = new UserServiceImpl();
// 获取当前类名
Class clazz = userService.getClass();
/*
* 2.获得代理对象。
* 每一个代理对象都有一个相关的InvocationHandler对象,通过这个handler对象的invoke来实现调用中要完成的自定义猫腻行为
* 。 可以使用Proxy类和自定义的调用处理逻辑来生成一个代理对象的。
*/
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
clazz.getClassLoader(), clazz.getInterfaces(),
new ProxyHandler(userService));
userServiceProxy.add(new User("dotjar"));
userServiceProxy.delete(new User("DDD"));
}
}
4.cglib动态代理
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
它的运行速度要远远快于JDK的Proxy动态代理。
使用CGLIB需要导入以下两个jar文件:
asm.jar – CGLIB的底层实现。
cglib.jar – CGLIB的核心jar包。
例子:
package com.niewj.service;
import java.lang.reflect.Method;
import com.niewj.model.User;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CgLibProxyImitation implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
/** 创建代理对象
* @param targetClass
* @return 返回代理对象
*/
@SuppressWarnings("rawtypes")
public Object getProxy(Class targetClass) {
enhancer.setSuperclass(targetClass); //设置需要创建子类的类
enhancer.setCallback(this);
return enhancer.create(); //通过字节码技术动态创建子类实例
}
public void cutIntoBefore(String mName) {
System.err.println("调用____" + mName + "()____方法之前");
}
public void cutIntoAfter(String mName) {
System.err.println("调用____" + mName + "()____方法完后");
}
/* 生成的代理对象调用此对象来替代原始对象
*
* @java.lang.Object 增强对象
* @java.lang.reflect.Method 拦截方法
* @java.lang.Object[] 参数数组
* @net.sf.cglib.proxy.MethodProxy 用于调用父类,按需要调用多次
*/
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
cutIntoBefore(method.getName());
Object result = proxy.invokeSuper(obj, args);
cutIntoAfter(method.getName());
return result;
}
public static void main(String[] args) {
// UserService userService = new UserServiceImpl();
CgLibProxyImitation cglib = new CgLibProxyImitation();
UserServiceImpl userService = (UserServiceImpl)cglib.getProxy(UserServiceImpl.class);
userService.add(new User("dotjar"));
userService.delete(new User("hill"));
}
}
jdk动态代理与cglib动态代理例子的更多相关文章
-
【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理
Spring AOP详解 . JDK动态代理.CGLib动态代理 原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...
-
Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)
一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...
-
java的静态代理、jdk动态代理和cglib动态代理
Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...
-
JDK动态代理和CGLib动态代理简单演示
JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期间创建接口的代理实例. 一.首先我们进行JDK动态代理的演示. 现在我们有一个简单的业务接口Saying,如下: package te ...
-
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
-
Spring 静态代理+JDK动态代理和CGLIB动态代理
代理分为两种:静态代理 动态代理 静态代理:本质上会在硬盘上创建一个真正的物理类 动态代理:本质上是在内存中构建出一个类. 如果多个类需要进行方法增强,静态代理则需要创建多个物理类,占用磁盘空间.而动 ...
-
Spring -- <;tx:annotation-driven>;注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。
借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...
-
Spring <;tx:annotation-driven>;注解 JDK动态代理和CGLIB动态代理 区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
-
从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式
从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...
随机推荐
-
【Win 10 应用开发】启动远程设备上的应用
这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...
-
【转】Caffe初试(七)其它常用层及参数
本文讲解一些其它的常用层,包括:softmax-loss层,Inner Product层,accuracy层,reshape层和dropout层及它们的参数配置. 1.softmax-loss sof ...
-
四则运算APP(BUG发掘)
BUG: 1.有几率会出现一样的题目. 2.题目会出现两个一样的答案. 3.做题结束后不能返回主界面或者重新开始. 感想: 1.题目应该按年级分类出题. 2.主界面可以添加更多功能 如自己输入题目数, ...
-
打造属于自己的vim利器
毋庸置疑vim很强大,然而没有插件的话对于大多数人来说他的界面是很不友好的.下面简单写一下我对vim的配置 这是我的vim配置,装的插件不是很多,对我来说已经够用.左边的侧边栏是NERD插件提供的,还 ...
-
thinkphp 杂乱笔记(1)
部署模式可用两个单入口表示前后台thinkphpUploadspublic Home(前台)Admin(后台)index.php(前台入口文件)admin.php(后台入口文件)上面两个项目目录 也可 ...
-
通过YAJL获取json中的值
这里主要是举例说明一下假设通过yajl获取json中的值. 对于array和object来说,获取的方式略有不同,详细能够參考以下的代码. 我仅仅是从网上搜集信息.知道有这么一种方法.假设还有别的方法 ...
-
卷积神经网络CNN公式推导走读
0有全连接网络,为什么还需要RNN 图像处理领域的特殊性, 全连接网络缺点: RNN解决办法: 1参数太多 ...
-
Spring的介绍与搭建
一.Spring的介绍 二.Spring的搭建 (1)导包 (2)创建一个对象 (3)书写配置注册对象到容器 (4)代码测试
-
hg命令
hg常用命令 hg命令跟git命令大同小异 hg version 查看hg版本 hg clone url 克隆代码仓库 hg branch newBranch 创建分支 hg update other ...
-
Protobuf使用手册
Protobuf使用手册 第1章 定义.proto 文件 首先我们需要编写一个 proto 文件,定义我们程序中需要处理的结构化数据,在 protobuf 的术语中,结构化数据被称为 Message. ...