java动态代理实现

Spring AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。jdk动态代理是由内部java的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。


cglib做动态代理时不要求被代理类实现统一接口。


来看一个我自己编写的jdk和cglib例子:

加入

代理类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import dynamicProxy.service.IHandler;

/**
 * Created by liukang Date: 2017/1/23 Time: 12:07 jdk 动态代理测试类T
 */
public  class  MyInvocationHandlerTest <ProxyClass> implements FactoryBean<ProxyClass> {

    private ProxyClass iHandler;
    /**
     * 代理类
     */
    private ProxyClass proxyIHandler;

    private _ProxyTypeEnum proxyTypeEnum;

    public MyInvocationHandlerTest(ProxyClass iHandler,_ProxyTypeEnum proxyTypeEnum){
        this.iHandler = iHandler;
        this.proxyTypeEnum = proxyTypeEnum;
    }

    public ProxyClass getObject() throws Exception {
        if(this.proxyTypeEnum.equals(_ProxyTypeEnum.JDK)){
            if (proxyIHandler == null) {
                _InvocationHandler myInvocationHandler = new _InvocationHandler();
                proxyIHandler = (ProxyClass) Proxy.newProxyInstance(this.iHandler.getClass().getClassLoader(),
                        this.iHandler.getClass().getInterfaces(), myInvocationHandler);
            }
        }

        if(this.proxyTypeEnum.equals(_ProxyTypeEnum.CGLIB)){
            Enhancer e = new Enhancer();
            e.setSuperclass(iHandler.getClass());
            e.setCallback(new _CglibProxy());
            proxyIHandler = (ProxyClass) e.create();
        }

        return proxyIHandler;
    }

    public Class<?> getObjectType() {
        return IHandler.class;
    }

    public boolean isSingleton() {
        return true;
    }

    public enum _ProxyTypeEnum{
        JDK,CGLIB;
    }

    /**
     * jdk代理类实现
     */
    public class _InvocationHandler implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object proxyObject = null;
            if ("handle".equals(method.getName())) {
                System.out.println("before handle!");
                proxyObject = method.invoke(MyInvocationHandlerTest.this.iHandler, args);
                System.out.println("end handle!");
            } else {
                proxyObject = method.invoke(MyInvocationHandlerTest.this.iHandler, args);
            }
            return proxyObject;
        }
    }

    /**
     * cglib代理类实现 cglib的好处是 代理的类不用都实现同一个接口
     */
    public class _CglibProxy implements MethodInterceptor{
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
            System.out.println(method.getName());
            Object o1 = methodProxy.invokeSuper(o, objects);
            System.out.println("++++++end " + methodProxy.getSuperName() + "++++++");
            return o1;
        }
    }

}

service层:

/**
 * Created by liukang
 * Date: 2017/1/23
 * Time: 12:15
 * 处理器接口
 */
public interface IHandler {
    void handle(Object...objects);
}
package dynamicProxy.service.impl;

import dynamicProxy.model.UserEntity;
import dynamicProxy.service.IHandler;

/**
 * Created by liukang Date: 2017/1/23 Time: 12:28 姓名处理类
 */
public class NameHandler implements IHandler {
    public void handle(Object... objects) {
        System.out.println("nameHandler start!");
        if (objects == null || objects.length < 1) {
            System.out.println("nameHandler objects is null");
            return;
        }
        UserEntity user = (UserEntity) objects[0];
        user.setName(user.getName()+" Handle");
        System.out.println("nameHandler done!");
    }
}
model层:

package dynamicProxy.model;

/**
 * Created by liukang
 * Date: 2017/1/23
 * Time: 12:48
 */
public class UserEntity {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public UserEntity(String name,int age){
        this.name = name;
        this.age = age;
    }
}

测试类:

import dynamicProxy.model.UserEntity;
import dynamicProxy.service.IHandler;
import dynamicProxy.service.impl.NameHandler;

/**
 * Created by liukang
 * Date: 2017/1/23
 * Time: 12:34
 */
public class TestProxy {
    public static void main(String args[]){
        //jdk
        MyInvocationHandlerTest<IHandler> myInvocationHandlerTest = new MyInvocationHandlerTest(new NameHandler(),
                MyInvocationHandlerTest._ProxyTypeEnum.JDK);
        UserEntity user = new UserEntity("name",16);
        try {
            IHandler nameHandler = myInvocationHandlerTest.getObject();
            nameHandler.handle(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(user.getName());
        //cglib
        MyInvocationHandlerTest<IHandler> myInvocationHandlerTest2 = new MyInvocationHandlerTest(new NameHandler(),
                MyInvocationHandlerTest._ProxyTypeEnum.CGLIB);
        UserEntity user2 = new UserEntity("name2",18);
        try {
            IHandler nameHandler2 = myInvocationHandlerTest2.getObject();
            nameHandler2.handle(user2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(user2.getName());
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值