基于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$$*继承于被代理的类,自然就不会出现类型转换失败的异常了。

原文地址:https://www.cnblogs.com/maheng/p/5433151.html