JDKProxy与CGlibProxy

Spring 使用动态代理技术实现AOP. spring AOP使用两种代理机制

  1.基于JDK代理

    JDK动态代理主要涉及两个类:Proxy和InvocationHandler,自定义实现InvocationHandler定义横切逻辑,并通过反射机制调用目标类代码,将横切逻辑和业务代码编织一起。

  Proxy通过InvocationHanbler动态创建某一接口实例,生成目标类代理对象。

  用一个接口模拟

/**
 * ee
 *
 * @author MM
 * @create 2018-03-28 17:16
 **/
public interface UserManage {
    void queryUser(String id);

    void addUser(String id, String name);
}
public class UserManagerImpl implements UserManage {


    @Override
    public void addUser(String id, String name) {
        System.out.println("新增用户:" + name);
    }

    @Override
    public void queryUser(String id) {
        System.out.println("查询用户:" + id);
    }
}

    

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

/**
 * eee
 *
 * @author MM
 * @create 2018-03-28 17:18
 **/
public class JDKProxyHandler implements InvocationHandler {
    //需要代理的目标对象
    private Object targetObject;


    public JDKProxyHandler(Object targetObject) {
        this.targetObject = targetObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //这里可以处理业务逻辑
        doService();

        return method.invoke(targetObject, args);
    }

    private void doService() {
        System.out.println("业务逻辑处理。。。");
    }

}

  测试代码

    public static void main(String[] args) {
        UserManage targetObject = new UserManagerImpl();

        JDKProxyHandler handler = new JDKProxyHandler(targetObject);
     //创建代理对象第二个参数即表明了JDK动态代理只能对实现了接口的类生成代理,而不能针对类,如果直接用类会抛异常
        UserManage userManagerJDK = (UserManage)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(), handler);

        userManagerJDK.addUser("tom", "test");

    }

 

  2.基于CGLib代理

    针对JDK动态代理只能对接口创建代理实例,CGLIb来弥补这一缺陷。CGLIb代理使用底层字节码技术,可以为类创建一个子类,在子类中采用方法拦截,去拦截父类方法的调用并织如横切逻辑。

  

/**
 * sgg
 *
 * @author MM
 * @create 2018-03-28 17:22
 **/
public class CGLibProxy implements MethodInterceptor {

    // CGLib需要代理的目标对象
    private Object targetObject;

    public Object getProxy(Object obj){
        this.targetObject = obj;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(this);
        return enhancer.create();

    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args,
                            MethodProxy methodProxy) throws Throwable {
        doService();
        return method.invoke(targetObject, args);
    }

    private void doService() {
        System.out.println("业务逻辑处理。。。");
    }
}
    public static void main(String[] args) {

        UserManage userManager = (UserManage) new CGLibProxy()
                .getProxy(new UserManagerImpl());
        userManager.addUser("tom", "test");

    }

 

 附上网上的总结:

spring对aop的支持

  *如果目标对象实现了接口,默认情况下会采用jdk的动态代理实现aop
  * 如果目标对象实现了接口,可以强制使用cglib实现aop
  *如果目标对象没有实现了接口,必须采用cglib库,spring会自动在jdk动态代理和cglib之间转换


如何强制使用cglib实现aop?
   * 添加cglib库,spring_home/cglib/*.jar
   * 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
 
jdk动态代理和cglib字节码生成的区别?
   * jdk动态代理只能对实现了接口的类生成代理,而不能针对类
   * cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
     因为是继承,所以该类或方法最好不要声明成final 

 

posted @ 2018-06-08 16:22  小阿Q的博客  阅读(277)  评论(0编辑  收藏  举报