• 动态代理(jdk&cglib)的用法


    什么是代理模式(Proxy)

    定义:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用

    在代理模式中,是需要代理对象和目标对象实现同一个接口

    为什么要用代理

    最最最主要的原因就是,在不改变目标对象方法的情况下对方法进行增强,比如,我们希望对方法的调用增加日志记录,或者对方法的调用进行拦截,等等...

    一:JDK动态代理

    JDK动态代理所用到的代理类在程序调用到代理类对象时才由JVM真正创建,JVM根据传进来的 业务实现类对象 以及 方法名 ,动态地创建了一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。

    案例

    1、定义业务接口以及实现类

    package com.yjc.jdkproxy;
    
    public interface DoSomeService {
        void doSome();
    }
    -------------------------------------------
    
    package com.yjc.jdkproxy;
    
    public class DoSomeServiceImpl implements DoSomeService {
        @Override
        public void doSome() {
            System.out.println("doSome++++++++++++++++++==");
        }
    }

    2.调用管理接口InvocationHandler 创建动态代理类

    package com.yjc.jdkproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class DoSomeHandler implements InvocationHandler {
      //这其实业务实现类对象,用来调用具体的业务方法
        private  Object target;
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before----------------------------");
          //调用真正的业务方法 Object invoke
    = method.invoke(target, args); System.out.println("after---------------------------"); return invoke; } public DoSomeHandler(Object target) { this.target = target;//接收业务实现类对象参数 } public DoSomeHandler() { } }

    测试方法

    package com.yjc.jdkproxy;
    
    import sun.misc.ProxyGenerator;
    
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.reflect.Proxy;
    
    public class JdkProxyTest {
        public static void main(String[] args) throws IOException {
            DoSomeService doSomeService=new DoSomeServiceImpl();
         //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
            //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
    DoSomeService o
    = (DoSomeService)Proxy.newProxyInstance(doSomeService.getClass().getClassLoader(), new Class[]{DoSomeService.class}, new DoSomeHandler(doSomeService));   //调用目标函数
         o.doSome();
          //将内存中代理的类生成到本地
    byte[] $proxy0s = ProxyGenerator.generateProxyClass("$proxy0", new Class[]{DoSomeService.class}); FileOutputStream fos=new FileOutputStream("F:/$proxy0.class"); fos.write($proxy0s); fos.flush(); fos.close(); } }

    二:CGLIB动态代理

         cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。

     cglib和jdk动态代理的区别就是,cglib无需业务接口也可以实现动态代理,而jdk是在业务接口的基础上进行实现的,没有接口不行。cglib也需要项目对cglib的支持,需要引入依赖

    业务类

    package com.yjc.cglibproxy;
    
    public class DoSomeServiceImpl {
    
        public void doSome() {
            System.out.println("doSome++++++++++++++++++==");
        }
    }

    代理类

    package com.yjc.cglibproxy;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class DoSomeHandler implements MethodInterceptor {
        //目标对象
        private  Object target;
    
    
        public DoSomeHandler(Object target) {
            this.target = target;
        }
    
        public DoSomeHandler() {
        }

    /**
    *
    * 方法描述 当对基于代理的方法回调时,在调用原方法之前会调用该方法
    * 拦截对目标方法的调用
    *
    * @param obj 代理对象
    * @param method 拦截的方法
    * @param args 拦截的方法的参数
    * @param proxy 代理
    * @return
    * @throws Throwable
    */

        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("before==========================");
            Object invoke = method.invoke(target, objects);
            System.out.println("after============================");
            return invoke;
        }
    }

    测试类

    package com.yjc.cglibproxy;
    
    import net.sf.cglib.proxy.Enhancer;
    
    public class CglibProxyTest {
        public static void main(String[] args) {
            Enhancer enhancer=new Enhancer(); 
    // 设置目标对象的Class
    enhancer.setSuperclass(DoSomeServiceImpl.class); 
      // 设置回调操作,相当于InvocationHandler
    enhancer.setCallback(new DoSomeHandler(new DoSomeServiceImpl()));
    DoSomeServiceImpl o
    =(DoSomeServiceImpl) enhancer.create();
    o.doSome();
    } }
  • 相关阅读:
    wtk2.1的问题
    扫雷大体完成了
    手机操作系统龟兔赛跑 Symbian深信将打败微软
    Practical UML™ A HandsOn Introduction for Developers
    有意思
    进展
    扫雷完成了:)
    Linux
    有关msn的api的两个网站
    csdn中讨论j2me之前途....
  • 原文地址:https://www.cnblogs.com/yjc1605961523/p/11753245.html
Copyright © 2020-2023  润新知