天天看点

JDK动态代理与CGLIB的区别

JDK动态代理和CGLIB字节码生成的区别?

        JDK动态代理只能对实现了接口的类生成代理,而不能针对类;

         CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。

(1)    JDK动态代理实例:

package com.designpatten.proxy;

/**
 * Created by lenovo on 2017/11/22.
 * 业务接口,提供对外提供的业务功能
 */
public interface UserService {
    /**
     * 目标方法
     */
    void  add();
}
package com.designpatten.proxy;
/**
 * Created by lenovo on 2017/11/22.
 * 业务接口实现类
 */
public class UserServiceImpl implements  UserService{
    @Override
    public void add() {
        System.out.println("这是业务方法!");
    }
}

package com.designpatten.proxy;

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

/**
 * Created by lenovo on 2017/11/22.
 * 创建自己的InvocationHandler,对业务方法进行增强
 */
public class MyInvocationHandler implements InvocationHandler{

    private Object target;

    public MyInvocationHandler(Object target){
        super();
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("--------before-----------");
        //执行目标对象的方法
        Object result = method.invoke(target,args);
        System.out.println("--------after-----------");
        return result;
    }

    /**
     * 获取目标对象的代理对象
     * @return
     */
    public Object getProxy(){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);
    }
}
package com.designpatten.proxy;

/**
 * Created by lenovo on 2017/11/22.
 */
public class TestProxy {
    public static void main(String[] args) {
        //实例化目标
        UserService userService = new UserServiceImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
        //根据目标对象生成代理
        UserService proxy =(UserService) myInvocationHandler.getProxy();
        proxy.add();
    }
}
 
           

运行结果:

--------before-----------

这是业务方法!

--------after-----------

(2) CGLIB使用实例:

package com.designpatten.proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * Created by lenovo on 2017/11/22.
 */
public class EnhancerDemo {
    public static void main(String[] args) {
        Enhancer enhancer  = new Enhancer();
        enhancer.setSuperclass(EnhancerDemo.class);
        enhancer.setCallback(new MethodInterceptorImpl());
        EnhancerDemo demo = (EnhancerDemo)enhancer.create();
        demo.test();
        System.out.println(demo);
    }
    public void test(){
        System.out.println("This is EnhancerDemo Test!");
    }

    private static class  MethodInterceptorImpl implements  MethodInterceptor{

        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.err.println("Before invoke"+method);
            Object result = methodProxy.invokeSuper(o,objects);
            System.err.println("After invoke"+method);
            return  result;
        }
    }
}
           

运行结果:

Before invokepublic void com.designpatten.proxy.EnhancerDemo.test()

This is EnhancerDemo Test!

After invokepublic void com.designpatten.proxy.EnhancerDemo.test()

Before invokepublic java.lang.String java.lang.Object.toString()

Before invokepublic native int java.lang.Object.hashCode()

After invokepublic native int java.lang.Object.hashCode()

After invokepublic java.lang.String java.lang.Object.toString()

[email protected]a67

可以看到在调用System.out.println(test)时,首先调用了toString()方法,然后又调用了hascode(),最后生成了[email protected]这个实例,这个类就是运行时CGLIB产生的。