1. 程式人生 > >關於jdk代理和cglib代理

關於jdk代理和cglib代理

implement ole start interface spa lib 調用方法 管理 todo

簡單的說說兩個代理的不同,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());
    }
}

關於jdk代理和cglib代理