精华内容
下载资源
问答
  • JDK动态代理代码示例

    2018-05-10 10:24:00
    JDK动态代理代码示例 业务接口 实现了业务接口的业务类 实现了InvocationHandler接口的handler代理类 1、业务接口 package com.wzq.demo01; /** * 业务接口 * * @author Muscleape * */ public interface...

    JDK动态代理代码示例

    1. 业务接口
    2. 实现了业务接口的业务类
    3. 实现了InvocationHandler接口的handler代理类

    1、业务接口

    package com.wzq.demo01;
    
    /**
     * 业务接口
     * 
     * @author Muscleape
     *
     */
    public interface UserService {
        /**
         * 增加一个用户
         */
        public void addUser();
    
        /**
         * 编辑账户
         */
        public void editUser();
    }
    

    2、业务接口实现类

    package com.wzq.demo01;
    
    /**
     * 业务接口实现类
     * 
     * @author Muscleape
     *
     */
    public class UserServiceImpl implements UserService {
    
        @Override
        public void addUser() {
            System.out.println("增加一个用户。。。");
        }
    
        @Override
        public void editUser() {
            System.out.println("编辑一个用户。。。");
        }
    
    }
    

    3、实现了InvocationHandler接口的handler代理类

    package com.wzq.demo01;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ServiceInvocationHandler implements InvocationHandler {
    
        /**
         * 目标对象
         */
        private Object target;
    
        /**
         * 构造函数
         * 
         * @param target
         */
        public ServiceInvocationHandler(Object target) {
            super();
            this.target = target;
        }
    
        /**
         * 实现InvocationHandler接口的方法
         * 
         * 执行目标对象的方法,并进行增强
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            Object result = null;
            System.out.println("代理类方法,进行增强。。。");
            System.out.println("事务开始。。。");
            // 执行目标方法对象
            result = method.invoke(target, args);
            System.out.println("事务结束。。。");
            return result;
        }
    
        /**
         * 创建代理实例
         * 
         * @return
         * @throws Throwable
         */
        public Object getProxy() throws Throwable {
            return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                    this.target.getClass().getInterfaces(), this);
            // 这样写只返回了目标对象,没有生成代理对象
            // return null;
        }
    
    }
    

    4、测试类

    package com.wzq.demo01;
    
    public class Test {
        /**
         * jdk动态代理会生成一个动态代理类,生成相应的字节码,然后通过ClassLoader加载字节码;
         * 
         * 该实例继承了Proxy类,并实现了业务接口,在实现的方法里通过反射调用了InvocationHandler接口实现类的invoke()回调方法;
         * 
         * @param args
         * @throws Throwable
         */
        public static void main(String[] args) throws Throwable {
            UserService userService = new UserServiceImpl();
            ServiceInvocationHandler handler = new ServiceInvocationHandler(userService);
    
            // 根据目标生成代理对象
            UserService proxy = (UserService) handler.getProxy();
            proxy.addUser();
        }
    }
    

    5、测试结果

    代理类方法,进行增强。。。
    事务开始。。。
    增加一个用户。。。
    事务结束。。。
    

    转载于:https://www.cnblogs.com/muscleape/p/9018302.html

    展开全文
  • 代理对象接口 被代理对象实现类 InvocationHandler实现类 测试类 运行结果 其中,创建代理对象的方法也可以分开写,InvocationHandler实现类中只传入被代理对象。然后在获取代理类对象中返回代理...

    被代理对象接口

    被代理对象实现类

    InvocationHandler实现类

    测试类

    运行结果

    其中,创建代理对象的方法也可以分开写,InvocationHandler实现类中只传入被代理对象。然后在获取代理类对象中返回代理对象,如下:

    调用方法如下:

     

     

     

     

     

     

     

    展开全文
  • 2、增强真实类的功能,且做到解耦,代理逻辑与业务逻辑是互相独立的,在不改变委托类代码情况下做一些额外处理,比如添加初始判断及其他公共操作(spring的AOP) 3、懒加载,程序启动时加载的是轻量级代理类,真实类...

    一、代理相关概念:被代理类(真实类),代理类
    二、代理的作用:
    1、无侵入式扩展代码,既增强功能,且做到解耦,代理逻辑与业务逻辑是互相独立,在不改变真实类代码情况下做一些额外处理(Spring AOP 事务控制、日志管理)。
    2、保护真实类(被代理类):代理类拦截对真实类的直接访问,对真实类做访问检查和控制,调用者只需要和代理类进行交互即可,不必关心真实类的实现细节。
    3、懒加载,程序启动时加载的是轻量级代理类,真实类只有在通过代理类调用的时候才会创建(Hibernate 的延迟加载(lazy load)本质上就是代理模式的应用,我们就经常通过代理模式来降低系统的内存开销、提升应用的运行性能。Hibernate 充分利用了代理模式的这种优势,并结合了 Javassist 或 CGLIB 来动态地生成代理对象,这更加增加了代理模式的灵活性,Hibernate 给这种用法一个新名称:延迟加载)。

    三、动态代理静态代理区别
    动态代理是一对多,静态代理一对一
    动态代理是在运行时动态成代理类放在内存中,静态代理运行前就已经生成代理类的.class文件

    四、jdk动态代理简单实现以及底层原理
    4-1 jdk动态代理简单实现:
    接口:Cooker.java

    public interface Cooker {
    	public void cook();
    }
    

    真实类(被代理类):ElectricCooker.java

    public class ElectricCooker implements Cooker {
    	@Override
    	public void cook() {
    		System.out.println("电饭锅煮饭");
    	}
    }
    

    InvocationHandler接口实现类:DynamicProxy.java

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    /**
     * Class<?> cl = getProxyClass0(loader, intfs);生成代理类
     */
    public class DynamicProxy implements InvocationHandler {
    	private Cooker target;
    	public Cooker getInstance(Cooker cooker ) {
    		this.target = cooker;
    		Class<?> clazz = target.getClass();
    		return (Cooker) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    	}
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		before();
    		Object obj = method.invoke(this.target, args);
    		after();
    		return obj;
    	}
    	private void before() {
    		System.out.println("before。。。插上电源");
    	}
    	private void after() {
    		System.out.println("after。。。拔掉电源");
    	}
    }
    

    测试类:DynamicProxyTest.java

    public class DynamicProxyTest {
    	String basePath = "C:/Users/zhou/Desktop/Jad/";
    
    	@Test
    	public void testCook() {
    		Cooker cooker = new DynamicProxy().getInstance(new ElectricCooker());
    		cooker.cook();
    	}
    
    	@Test
    	public void testGetClassFile() {
    		Cooker cooker = new DynamicProxy().getInstance(new ElectricCooker());
    		byte[] classFile = sun.misc.ProxyGenerator.generateProxyClass(cooker.getClass().getName(),
    				cooker.getClass().getInterfaces());
    		String path = basePath + cooker.getClass().getSimpleName() + ".class";
    		try (FileOutputStream fos = new FileOutputStream(path)) {
    			fos.write(classFile);
    			fos.flush();
    			System.out.println("代理类class文件写入成功,classNme:" + cooker.getClass().getName());
    		} catch (Exception e) {
    			e.printStackTrace();
    			System.out.println("写文件错误");
    		}
    	}
    }
    

    测试结果 testCook():

    before。。。插上电源
    电饭锅煮饭
    after。。。拔掉电源
    

    测试结果 testGetClassFile(),通过jad反编译得到动态生成的代理类$Proxy4代码:

    package com.uniz.study.proxy.source;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    import com.uniz.study.proxy.Cooker;
    
    public final class $Proxy4 extends Proxy implements Cooker {
    	private static Method m1;
    	private static Method m2;
    	private static Method m3;
    	private static Method m0;
    
    	static {
    		try {
    			m1 = Class.forName("java.lang.Object").getMethod("equals",
    					new Class[] { Class.forName("java.lang.Object") });
    			m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
    			m3 = Class.forName("com.uniz.study.proxy.Cooker").getMethod("cook", new Class[0]);
    			m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	public $Proxy4(InvocationHandler paramInvocationHandler) {
    		super(paramInvocationHandler);
    	}
    
    	public final void cook() {
    		try {
    			this.h.invoke(this, m3, null);
    			return;
    		} catch (RuntimeException localRuntimeException) {
    			throw localRuntimeException;
    		} catch (Throwable localThrowable) {
    			throw new UndeclaredThrowableException(localThrowable);
    	}
    	}
    
    	public final boolean equals(Object paramObject)
      {
        try
        {
          return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    
    	public final String toString()
      {
        try
        {
          return (String)this.h.invoke(this, m2, null);
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    	public final int hashCode()
      {
        try
        {
          return ((Integer)this.h.invoke(this, m0, null)).intValue();
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    }
    

    Proxy.java
    在这里插入图片描述
    在这里插入图片描述

    4-2 通过上面testGetClassFile()测试方法分析动态代理底层逻辑实现:

    Cooker cooker = new DynamicProxy().getInstance(new ElectricCooker());
    此处cooker的实际类型是动态生成的代理类$Proxy4,

    1、$Proxy4的实现了Cooker 接口:

    public final void cook() {
    		try {
    			this.h.invoke(this, m3, null);
    			return;
    		} catch (RuntimeException localRuntimeException) {
    			throw localRuntimeException;
    		} catch (Throwable localThrowable) {
    			throw new UndeclaredThrowableException(localThrowable);
    	}
    

    2、方法中this.h是$Proxy4类的属性protected InvocationHandler h,在生成动态代理类时,DynamicProxy 把自己作为参数传给了代理类,因此此处this.h = DynamicProxy对象,而DynamicProxy类刚好实现了InvocationHandler接口的invoke方法,并且invoke方法中执行method.invoke(target, args)时,参数target是真实类的对象引用,因而能执行真实对象的方法

    五、debug跟踪动态代理类的详细创建过程:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    至此,由上面debug过程发现,代理类$Proxy4的关键创建过程如下:

    Cooker cooker = new DynamicProxy().getInstance(new ElectricCooker());
    Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this)
    Class<?> cl = getProxyClass0(loader, intfs);
    valueFactory.apply(key, parameter)
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);
    最后发现创建代理类的方法 ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);
    测试方法testGetClassFile()正是调用此方法得到代理对象$Proxy4
    

    小结:
    1、真实类(被代理类)把自己委托给代理类,在代理类中可以对其功能增强,同时做到代理逻辑与业务逻辑的解耦,当真实类比较臃肿时,初始化时用轻量级的代理类替代直接初始化真实类,从而实现真实类的延迟加载。
    2、jdk的动态代理简单实现逻辑:

    // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
    InvocationHandler handler = new InvocationHandlerImpl(..); 
     
    // 通过 Proxy 直接创建动态代理类实例
    Interface proxy = (Interface)Proxy.newProxyInstance( classLoader, 
         new Class[] { Interface.class }, 
         handler );
    

    3、常见的代理场景:
    远程代理:为位于两个不同地址空间对象的访问提供了一种实现机制,可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高系统的整体运行效率。
    虚拟代理:通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销
    缓存代理:为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,优化系统性能,缩短执行时间
    保护代理:可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限。
    智能引用代理:当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理

    参考:
    Java 动态代理机制分析及扩展

    java动态代理实现与原理详细分析

    JAVA动态代理

    代理模式 | 菜鸟教程

    JDK动态代理|ProxyGenerator生成代理类的字节码文件解析

    展开全文
  • 实现java动态代理的两个实例,jdk动态代理和cglib
  • 动态代理在Java中有JDK动态代理和CGLIB动态代理,也就是在运行中动态生成字节码并加载到虚拟机中供我们后续使用。下面我们先看下这两种方式的区别。 两者区别: JDK动态代理:需要被代理对象的类实现了某些接口,...

    觉得可以的话点个关注转个发,加个收藏呗,陆续奉上干货~~~~

    开始~~

    动态代理在Java中有JDK动态代理和CGLIB动态代理,也就是在运行中动态生成字节码并加载到虚拟机中供我们后续使用。下面我们先看下这两种方式的区别。

    两者区别:

    JDK动态代理需要被代理对象的类实现了某些接口,生成的代理类也会实现相应的接口

    CGLIB动态代理:不需要被代理对象的类实现了某些接口,生成的代理类为目标对象的类的子类

    动态代理——JDK动态代理原理&示例解析(图文并茂)

    下面我们对JDK动态代理进行解析:(源码见下方)

    1、java.lang.reflect.Proxy:根据InvocationHandler和目标类的类加载器,实现的接口生成代理类,生成的代理类也实现了这些接口,且使用相同的类加载器加载,然后再反射生成代理类的实例,反射生成的过程中会将InvocationHandler传递给父类的构造方法,因此实例化的代理类对象会持有InvocationHandler的引用

    2、InvocationHandler包含具体的被代理对象的引用,也代码中也就是target字段,根据invoke方法执行相应的操作

    3、最终生成的代理类会继承Proxy类并实现HelloService接口

    接口和实现类:

    动态代理——JDK动态代理原理&示例解析(图文并茂)

    生成的代理类:

    final class $Proxy0 extends Proxy implements HelloService

    先看下代理类生成的流程图:步骤和生成的代理类的代码结构对应(源码如下)

    通过配置系统属性可以在本地磁盘生成代理类的Class文件:(在源码中可以追踪到对这个系统属性值的判断)

    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

    动态代理——JDK动态代理原理&示例解析(图文并茂)

    自定义InvocationHandler:

    动态代理——JDK动态代理原理&示例解析(图文并茂)

    测试:

    动态代理——JDK动态代理原理&示例解析(图文并茂)

    代理对象(proxyObject)的创建及hello方法执行流程图

    1、实例化目标对象

    2、根据目标对象构造MyInvocationHandler实例,

    3、将MyInvocationHandler实例传递给代理类$Proxy0的构造方法来实例化代理类对象

    proxyObject在该过程中会初始化父类成员变量InvocationHandler类型的h字段

    public $Proxy0(InvocationHandler handler) throws  {
        // 调用父类构造方法
        // 将handler赋值给成员变量:InvocationHandler类型的h
        super(handler); 
    }

    4、因为生成的代理类也实现了接口HelloService,代理对象proxyObject可以强转为HelloService类型。然后执行代理对象proxyObject的hello方法:

    String returnValue = ((HelloService) proxyObject).hello();

    解析:根据生成的代理类的代码来看,调用hello方法实际调用的是父类的h变量指向的对象的invoke方法,也就是我们定义的MyInvocationHandler中的invoke方法,参数分别为当前代理对象proxyObject当前执行的方法m3参数数组null

    public final String hello()  {
        return (String)super.h.invoke(this, m3, (Object[])null);
    }
    m3 = Class.forName("com.ww.jvm.dynamicproxy.HelloService").getMethod("hello");
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(
                         Object proxy,  // 当前代理对象
                         Method method, // 当前执行的方法
                         Object[] args) throws Throwable {
        String methodName = method.getName();
        System.err.println("before invoke " + methodName);
        Object returnValue = method.invoke(target, args);
        System.err.println("after invoke " + methodName);
        return returnValue;
    }

    总结JDK动态代理执行代理对象方法实际上是调用的是我们自定义的MyInvocationHandler中的invoke方法,而执行的具体是哪个方法都已经提前初始化到动态生成的代理类$Proxy0的字段中了,也就是生成的代理类中的字段m0、m1、m2、m3,这几个字段分别代表了Object类中的 hashCode方法、equals方法、toString方法和我们自己的接口中的hello方法。

    觉得可以的话点个关注转个发,加个收藏呗,陆续奉上干货~~~~

    Ps:CGLIB动态代理后续给出~~~

    再次上图,加深印象:

    动态代理——JDK动态代理原理&示例解析(图文并茂)

     

    展开全文
  • jdk动态代理 实现步骤 新建一个接口 新建一个接口的实现类 新建一个代理类,实现InvocationHandler接口,实现invoke方法-> method.invoke(…) 在代理类中创建代理方法newProxy,传入目标对象,通过目标对象获取...
  • JDK动态代理就是在程序运行时,运用反射机制动态创建代理类,实现对目标类代码的增强。动态代理类的字节码在程序运行时由Java反射机制动态生成,不需要去手动开发。相比较静态代理,它更灵活。更容易扩展,代码 开发...
  • 主要介绍了Java JDK动态代理实现原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • JDK和cglib动态代理代码: package com.zhangxueliang.demo.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ...
  • 1 JDK动态代理(必须要有接口) 接口 package com.itykd.dao; public interface UserDao { void save(); void update(); void find(); void delete(); } 实现类 package com.itykd.dao.impl; import ...
  • Java两种动态代理JDK动态代理和CGLIB动态代理

    万次阅读 多人点赞 2018-08-07 15:33:35
    JDK动态代理 cglib动态代理 测试 代理模式 代理模式是23种设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式。为了对外开放协议,B往往实现了一个接口,A也会去实现接口。但是B是...
  • 实例理解JDK动态代理和Cglib动态代理及其区别 深入理解设计模式之代理模式 代理代理化妆品生产理解JDK动态代理 代理代理汽车制造理解Cglib动态代理
  •   JDK动态代理代理模式的一种实现方式。因为它是基于接口来做代理的,所以也常被称为接口代理。在JDK动态代理中有两个重要的角色: InvocationHandler(Interface) 用户实现这个接口,用来编写代理类处理的核心...
  • JDK动态代理实例

    2018-12-09 19:06:07
    在使用SpingMVC做WEB应用层架构时,经常使用SpringAOP实现数据库事务控制,SpringAOP使用动态代理,有两种,JDK代理和cglib代理,默认使用JDK代理。但JDK代理只能为接口创建代理实例。今天主要以简单代码说明JDK代理...
  • 一个简单的动态代理实现://目标对象需要实现的接口package reflection.DynamicProxy; public interface UserDao { void findUserByUserCode(String userCode); void findUserByEmai(String email); }//目标对象...
  • 引入代理模式 代理模式是框架中经常使用的一种模式,动态代理是AOP(面向切面编程)思想的一种重要的实现方式...在Hibernate中对象的懒加载模式,也运用了JDK动态代理以及cglib代理。 静态代理 在说动态代理之...
  • 主要介绍了Spring JDK动态代理实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • JAVA动态代理代码示例

    千次阅读 2019-04-11 13:49:28
    代理是一种软件设计模式,目的地希望能做到代码重用。代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过...
  • } } 3 JDK动态代理 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 1. 首先实现一个InvocationHandler,方法调用会被转发到该类的invoke()...
  • 为什么JDK动态代理要基于接口实现而不能基于继承实现? 1. 问题 在阅读本文之前,可以先思考一下下面几个问题。 为什么说JDK动态代理要基于接口实现,而不能基于继承来实现? 在JDK动态代理中,在目标对象...
  • JDK动态代理 核心思想:通过实现被代理类的所有接口,生成一个字节码文件后构造一个代理对象,通过持有反射构造被代理类的一个实例,再通过invoke反射调用被代理类实例的方法,来实现代理...JDK代理生成的代理类的...
  • 面试必备技能:JDK动态代理给Spring事务埋下的坑!

    万次阅读 多人点赞 2018-01-10 21:38:38
    最近做项目遇到了一个很奇怪的问题,大致的业务场景是这样的:我们首先设定两个事务,事务parent和事务child,在Controller里边同时调用这两个方法,示例代码如下: 1、场景A: @RestController @RequestMapping...
  • 最近在看Spring AOP,里面使用到了动态代理,自己对两种代理模式进行了学习,这里做个总结。本文主要介绍动态代理,开始之前还是先介绍一下代理的相关内容。 一、代理 代理分为静态代理动态代理,无论哪种代理,...
  • Java两种动态代理JDK动态代理和CGLIB动态代理 静态代理(需要一个目标类写一个代理类) 使用代理模式可以在不影响原有代码(目标类方法)的情况下,增强功能逻辑 实现步骤 1. 相同接口 public interface Caculator { int...
  • 概述 使用过spring aop的人应该都知道,spring是通过动态代理来实现的。...jdk动态代理示例 这里举个简单的例子,普通人要买票,但是自己买票一般都买不到的,于是,可以让黄牛代为买票。 publi...
  • JDK动态代理为什么不能代理

    千次阅读 2019-10-15 07:55:17
    戳蓝字「TopCoder」关注我们哦!关于JDK动态代理,想必小伙伴都知道,它只能代理接口!但是有的小伙伴可能会有疑问,为什么它只能代理接口,不能代理类呢?这里借助某位技...
  • jdk动态代理示例以及代码原理分析

    千次阅读 2016-12-09 14:49:21
    本文通过根据JDK源码,展示这些细节,以期能对JDK动态代理有深入的理解。 简单示例代码 public class ProxyInstance implements Product { public void show() { System.out.println("这是原本

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,471
精华内容 10,188
热门标签
关键字:

jdk动态代理代码示例