关于jdk代理和cglib代理

  简单的说说两个代理的不同,CGLIB代理可以视为JDK代理的补充,JDK的代理是基于接口来实现的,也就是说使用JDK代理的类必须包含至少一个接口,调用代理的方法时,会不断地找寻接口中与调用方法匹配的值,然后通过反射找到此接口的方法,调用InvocationHandler的invoke方法拦截代理。

  再说CGLIB,与JDK不同,CGLIB不要求代理类必有什么接口的,它通过制造一个类,通过继承的方式实现代理类,类似于钩子回调,也就是说CGLIB要求代理的类不能是final调用的方法也不能是final的。通过查看各开源框架,也能够发现使用CGLIB代理,反射,泛型等乱七八糟的方法比较多。

cglib有两种可选方式,继承和引用。第一种是基于继承实现的动态代理,所以可以直接通过super调用target方法,但是这种方式在spring中是不支持的,因为这样的话,这个target对象就不能被spring所管理,所以cglib还是才用类似jdk的方式,通过持有target对象来达到拦截方法的效果。通过CGLIB代理可以很大程度的增强代理方法。如spring中AOP相关的拦截方法,和hibernate中,毕竟hibernate中有大量的缓存机制和ORM工具方法。当然我并没有说JDK代理要比CGLIB好。在框架中二中代理都被大量的使用,并且在spring中如spring AOP中默认是使用JDK代理实现来实现接口,你可以强制使用CGLIB。在使用struts2框架时,你可能碰到过一种莫名奇妙的场景,就是使用ActionAware接口时,调用代理方法报错找不到有关的方法,这很可能是因为Spring关注到你的action实现了某个接口,于是为你使用JDK代理,进而使你调用的方法不被找到。

那么接下来请参照下面两段代码,进一步理解

首先是基础工作,一个接口:

public interface UserService {
    Boolean addUser(User user);
}

实现类

public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;// 插入用户 用户id用uuid
    @Override
    public Boolean addUser(User user) {
        user.setRole_id(11001);
        user.setActivecode(UUID.randomUUID().toString().replace("-", ""));
        user.setUser_id(UUID.randomUUID().toString().replace("-", ""));
        user.setRegister(new Date());
        return true;//此处请无视// TODO

    }
}

 

这里是代理的实现

package com.dabai.test

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
 
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
 
    MyInvocationHandler() {
        super();
    }
 
    MyInvocationHandler(Object target) {
        super();
        this.target = target;
    }
 
    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
        if("getName".equals(method.getName())){
            System.out.println("start--" + method.getName());
            Object result = method.invoke(target, args);
            System.out.println("end--" + method.getName());
            return result;
        }else{
            Object result = method.invoke(target, args);
            return result;
        }
 
    }
} 

这里调用

package com.dabai.test.jdk;
 
package com.dabai.mytwo.service;
package com.dabai.mytwo.service.impl;

import com.dabai.mytwo.entity.User;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Proxy_Jdk { public static void main(String[] args) { UserService userService = new UserServiceImpl(); InvocationHandler invocationHandler = new MyInvocationHandler(userService); UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler); userServiceProxy.addUser(new User()); } }

接下来是CGLIB代理

package com.dabai.test.cglib;
 
 
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import java.lang.reflect.Method;
 
 
public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("start cg----" + methodProxy.getSuperName());
        System.out.println(method.getName());
        Object obj = methodProxy.invokeSuper(o, args);
        System.out.println("end----" + methodProxy.getSuperName() );
        return obj;
    }
}
package com.dabai.test.cglib;
 
package com.dabai.mytwo.service;
package com.dabai.mytwo.service.impl
import net.sf.cglib.proxy.Enhancer;
 
 
 
public class Proxy_Cglib {
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
 //在此处增强代理方法
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserServiceImpl.class);
        enhancer.setCallback(cglibProxy);
 
        UserService userService = (UserService)enhancer.create();
        userService.addUser(new User());
    }
}

 

posted @ 2019-05-01 21:14  落楝花  阅读(1058)  评论(0编辑  收藏  举报

乘兴而来