zoukankan      html  css  js  c++  java
  • 基于jdk和cglib的动态代理

      动态代理是Spring Aop的基础,分为基于JDK的动态代理(接口实现)和基于CGLIB的动态代理(继承实现)。

      

      声明一个被代理的类:

    package com.maheng.proxy.jdk;
    
    public interface IUser {
        
        public void save(String name);
    }
    package com.maheng.proxy.jdk;
    
    public class User implements IUser{
    
        @Override
        public void save(String name) {
            System.out.println("save " + name);
        }
    
    }

      

      使用装饰模式来实现静态代理:

    package com.maheng.proxy.jdk;
    
    public class StaticProxy implements IUser{
        private IUser target;
        
        public StaticProxy(IUser target){
            this.target = target;
        }
    
        @Override
        public void save(String name) {
            System.out.println("begin save");
            target.save(name);
            System.out.println("end save");
        }
        
        
    }

      基于JDK的动态代理:

    package com.maheng.proxy.jdk;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    /*
     * 基于jdk的动态代理
     * @autor maheng
     * @date 2016.4.25
     * */
    public class DynamicProxy implements InvocationHandler{
        private Object target;
        
        public Object proxy(Object target){
            this.target = target;
            // 动态创建一个代理对象
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
        
        /**
         * 调用代理对象的任何方法,都会执行该方法
         * 相当于拦截代理对象的方法
         * */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            Object resout = null;
            System.out.println(proxy.getClass());
            System.out.println("begin");
            resout = method.invoke(target, args);
            System.out.println("end");
            return resout;
        }
    }

      测试用例:

    package com.maheng.proxy.jdk;
    
    
    public class Test {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		StaticProxy staticProxy = new StaticProxy(new User());
    		staticProxy.save("maheng");
    		System.out.println(staticProxy.getClass());
    		System.out.println("=============");
    		
    		DynamicProxy dynamicProxy = new DynamicProxy();
    		IUser user = (IUser)dynamicProxy.proxy(new User());
    		user.save("yuanmeng");
    		System.out.println(user.getClass());
    	}
    
    }

      

      基于cglib的动态代理:

    package com.maheng.proxy.cglib;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.InvocationHandler;
    
    /*
     * 基于cglib的动态代理
     * @autor maheng
     * @date 2016.4.25
     * */
    public class DynamicProxy implements InvocationHandler{
        private Object target;
        
        public Object proxy(Object target){
            this.target = target;
            Enhancer enhancer = new Enhancer();
            enhancer.setClassLoader(target.getClass().getClassLoader());
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        /**
         * 调用代理对象的任何方法,都会执行该方法
         * 相当于拦截代理对象的方法
         * */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            Object resout = null;
            System.out.println(proxy.getClass());
            System.out.println("begin");
            System.out.println(target.getClass());
            resout = method.invoke(target, args);
            System.out.println("end");
            return resout;
        }
    }

      测试用例:

    package com.maheng.proxy.cglib;
    
    import com.maheng.proxy.jdk.IUser;
    import com.maheng.proxy.jdk.User;
    
    public class Test {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            DynamicProxy dynamicProxy = new DynamicProxy();
            IUser user = (User)dynamicProxy.proxy(new User());
            System.out.println(user.getClass());
            user.save("maheng");
            
        }
    
    }

      在使用自动代理时, 在<aop:aspectj-autoproxy proxy-target-class="false"/>标签中设置 proxy-target-class="fasle/true" ,false采用基于jdk的动态代理,true采用基于cglib的动态代理。

      在使用基于jdk的动态代理时,如果出现java.lang.ClassCastException,将需要代理的类用接口实现就可以避免这个问题,原因是:产生的代理类$Proxy0和被代理的类之间没有直接关系,强制类型转换自然会失败,先声明接口那么产生的代理类$Proxy0和被代理的类实现了相同的接口,就可以使得$Proxy0类型转换为定义的接口类型来避免这个问题。而基于cglib的动态代理中产生的代理类*$$EnhancerByCGLIB$$*继承于被代理的类,自然就不会出现类型转换失败的异常了。

  • 相关阅读:
    浮点数
    2020.07.13
    2020.07.07
    2020.07.06
    剑指offer(三)
    剑指offer(二)
    剑指offer
    堆排序
    归并排序
    希尔排序
  • 原文地址:https://www.cnblogs.com/maheng/p/5433151.html
Copyright © 2011-2022 走看看