jdk动态代理与cglib动态代理例子

时间:2023-02-17 23:29:29

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动态代理例子的更多相关文章

  1. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

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

    一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...

  3. java的静态代理、jdk动态代理和cglib动态代理

    Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...

  4. JDK动态代理和CGLib动态代理简单演示

    JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期间创建接口的代理实例. 一.首先我们进行JDK动态代理的演示. 现在我们有一个简单的业务接口Saying,如下: package te ...

  5. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(&commat;Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  6. Spring 静态代理&plus;JDK动态代理和CGLIB动态代理

    代理分为两种:静态代理 动态代理 静态代理:本质上会在硬盘上创建一个真正的物理类 动态代理:本质上是在内存中构建出一个类. 如果多个类需要进行方法增强,静态代理则需要创建多个物理类,占用磁盘空间.而动 ...

  7. Spring -- &lt&semi;tx&colon;annotation-driven&gt&semi;注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(&commat;Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  8. Spring &lt&semi;tx&colon;annotation-driven&gt&semi;注解 JDK动态代理和CGLIB动态代理 区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  9. 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式

    从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...

随机推荐

  1. 【Win 10 应用开发】启动远程设备上的应用

    这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...

  2. 【转】Caffe初试(七)其它常用层及参数

    本文讲解一些其它的常用层,包括:softmax-loss层,Inner Product层,accuracy层,reshape层和dropout层及它们的参数配置. 1.softmax-loss sof ...

  3. 四则运算APP(BUG发掘)

    BUG: 1.有几率会出现一样的题目. 2.题目会出现两个一样的答案. 3.做题结束后不能返回主界面或者重新开始. 感想: 1.题目应该按年级分类出题. 2.主界面可以添加更多功能 如自己输入题目数, ...

  4. 打造属于自己的vim利器

    毋庸置疑vim很强大,然而没有插件的话对于大多数人来说他的界面是很不友好的.下面简单写一下我对vim的配置 这是我的vim配置,装的插件不是很多,对我来说已经够用.左边的侧边栏是NERD插件提供的,还 ...

  5. thinkphp 杂乱笔记&lpar;1&rpar;

    部署模式可用两个单入口表示前后台thinkphpUploadspublic Home(前台)Admin(后台)index.php(前台入口文件)admin.php(后台入口文件)上面两个项目目录 也可 ...

  6. 通过YAJL获取json中的值

    这里主要是举例说明一下假设通过yajl获取json中的值. 对于array和object来说,获取的方式略有不同,详细能够參考以下的代码. 我仅仅是从网上搜集信息.知道有这么一种方法.假设还有别的方法 ...

  7. 卷积神经网络CNN公式推导走读

      0有全连接网络,为什么还需要RNN 图像处理领域的特殊性,      全连接网络缺点:                              RNN解决办法:      1参数太多       ...

  8. Spring的介绍与搭建

    一.Spring的介绍 二.Spring的搭建 (1)导包 (2)创建一个对象 (3)书写配置注册对象到容器 (4)代码测试

  9. hg命令

    hg常用命令 hg命令跟git命令大同小异 hg version 查看hg版本 hg clone url 克隆代码仓库 hg branch newBranch 创建分支 hg update other ...

  10. Protobuf使用手册

    Protobuf使用手册 第1章 定义.proto 文件 首先我们需要编写一个 proto 文件,定义我们程序中需要处理的结构化数据,在 protobuf 的术语中,结构化数据被称为 Message. ...