關於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()); } }
關於jdk代理和cglib代理