『壹』 Spring的兩種代理JDK和CGLIB的區別淺談
一、原理區別
java動態代理是利用反射機制生成一個實現代理介面的匿名類,在調用具體方法前調用InvokeHandler來處理。
而cglib動態代理是利用asm開源包,對代理對象類的class文件載入進來,通過修改其位元組碼生成子類來處理。
1、如果目標對象實現了介面,默認情況下會採用JDK的動態代理實現AOP
2、如果目標對象實現了介面,可以強制使用CGLIB實現AOP
3、如果目標對象沒有實現了介面,必須採用CGLIB庫,spring會自動在JDK動態代理和CGLIB之間轉換
如何強制使用CGLIB實現AOP?
(1)添加CGLIB庫,SPRING_HOME/cglib/*.jar
(2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
JDK動態代理和CGLIB位元組碼生成的區別?
(1)JDK動態代理只能對實現了介面的類生成代理,而不能針對類
(2)CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法
因為是繼承,所以該類或方法最好不要聲明成final
二、代碼實現
[html] view plain
package com.fy.spring.proxy;
public interface UserManager {
public void addUser(String id, String password);
public void delUser(String id);
}
[html] view plain
package com.fy.spring.proxy;
public class UserManagerImpl implements UserManager {
public void addUser(String id, String password) {
System.out.println(".: 掉用了UserManagerImpl.addUser()方法! ");
}
public void delUser(String id) {
System.out.println(".: 掉用了UserManagerImpl.delUser()方法! ");
}
}
JDK動態代理類
[html] view plain
package com.fy.spring.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
*
* JDK動態代理類
*
*
*/
public class JDKProxy implements InvocationHandler {
private Object targetObject;//需要代理的目標對象
public Object newProxy(Object targetObject) {//將目標對象傳入進行代理
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);//返回代理對象
}
public Object invoke(Object proxy, Method method, Object[] args)//invoke方法
throws Throwable {
checkPopedom(); //一般我們進行邏輯處理的函數比如這個地方是模擬檢查許可權
Object ret = null; // 設置方法的返回值
ret = method.invoke(targetObject, args); //調用invoke方法,ret存儲該方法的返回值
return ret;
}
private void checkPopedom() {//模擬檢查許可權的例子
System.out.println(".:檢查許可權 checkPopedom()!");
}
}
CGLibProxy動態代理類
[html] view plain
package com.fy.spring.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* CGLibProxy動態代理類的實例
*
*
*/
public class CGLibProxy implements MethodInterceptor {
private Object targetObject;// CGLib需要代理的目標對象
public Object createProxyObject(Object obj) {
this.targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
return proxyObj;// 返回代理對象
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object obj = null;
if ("addUser".equals(method.getName())) {// 過濾方法
checkPopedom();// 檢查許可權
}
obj = method.invoke(targetObject, args);
return obj;
}
private void checkPopedom() {
System.out.println(".:檢查許可權 checkPopedom()!");
}
}
測試類:
[html] view plain
public class Client {
public static void main(String[] args) {
UserManager userManager = (UserManager) new CGLibProxy()
.createProxyObject(new UserManagerImpl());
System.out.println("-----------CGLibProxy-------------");
userManager.addUser("tom", "root");
System.out.println("-----------JDKProxy-------------");
JDKProxy jdkPrpxy = new JDKProxy();
UserManager userManagerJDK = (UserManager) jdkPrpxy
.newProxy(new UserManagerImpl());
userManagerJDK.addUser("tom", "root");
}
}
運行結果:
[html] view plain
-----------CGLibProxy-------------
檢查許可權 checkPopedom()!
掉用了UserManagerImpl.addUser()方法!
-----------JDKProxy-------------
檢查許可權 checkPopedom()!
掉用了UserManagerImpl.addUser()方法!
三、區別
JDK代理是不需要依賴第三方的庫,只要JDK環境就可以進行代理,它有幾個要求
* 實現InvocationHandler
* 使用Proxy.newProxyInstance產生代理對象
* 被代理的對象必須要實現介面
使用JDK動態代理,目標類必須實現的某個介面,如果某個類沒有實現介面則不能生成代理對象。
CGLib 必須依賴於CGLib的類庫,Cglib原理是針對目標類生成一個子類,覆蓋其中的所有方法,所以目標類和方法不能聲明為final類型。針對介面編程的環境下推薦使用JDK的代理。從執行效率上看,Cglib動態代理效率較高。在Hibernate中的攔截器其實現考慮到不需要其他介面的條件Hibernate中的相關代理採用的是CGLib來執行。
『貳』 高分100,一個簡單問題,JAVA集成環境NetBeans IDE 各個文件夾都是干什麼的
文件夾:build-存放編譯後抄的class文件
nbproject-存放項目的具體配置文件
src-java源代碼存放文件夾
test-JUnit測試文件存放位置
Build.xml構建描述文件,因為Netbeans的編譯打包是基於ant的,build就是ant實現自動編譯打包的描述文件。
manifest.mf是打包的時候需要的一個清單文件,是對打包後的jar包中的文件的一個描述下文件。
original.java,.netbeans_automatic_build,這兩個文件不知道你用的什麼Netbeans版本,在我的版本中並未生成此文件。
build-impl.xml是對Build.xml文件的具體描述,Build.xml其實並未實現具體的ant構建腳本,具體是在該文件中實現的,如果你看過build.xml的源代碼,就會發現一句<import file="nbproject/build-impl.xml"/>,這你就知道是什麼意思了。