代理模式是對象的結構型模式,代碼模式給某一個對象提供代理,並由代理對象控制原對象(目標對象,被代理對象)的引用。簡單點說,就是經過一個工廠生成一個類的代理對象,當客戶端使用的時候不直接使用目標對象,而是直接使用代理對象。代理對象至關於中介.java
public interface UserService { web
public void addUser(String userId,String userName); spring
} ide
public class UserServiceImpl implements UserService {測試
@Overridethis
public void addUser(String userId, String userName) {spa
System.out.println("UserServiceImpl addUser userId->>"+userId);.net
}代理
}對象
(代理類持有被代理類的引用)
public class UserServiceImplProxy implements UserService {
private UserService userService;
public UserServiceImplProxy(UserService userService){
this.userService = userService;
}
@Override
public void addUser(String userId, String userName) {
try {
System.out.println("開始執行:addUser");
userService.addUser(userId, userName);
System.out.println("addUser執行成功。");
} catch (Exception e) {
System.out.println("addUser執行失敗。");
}
}
}
public class Client {
public static void main(String[] args) {
UserService userService = new UserServiceImplProxy(new UserServiceImpl());
userService.addUser("001", "centre");
}
}
須要爲每個目標類建立一個代理類,須要創建大量的代理類,耦合度高.違背了重複代碼只寫一次的原則.
Jdk的動態要求目標對象必須實現接口,由於它建立代理對象的時候是根據接口建立的。若是不實現接口,jdk沒法給目標對象建立代理對象。被代理對象能夠能夠實現多個接口,建立代理時指定建立某個接口的代理對象就能夠調用該接口定義的方法了
public interface Service {
public void sayHello(String name);
}
public class UserServiceImpl implements UserService ,Service{
@Override
public void addUser(String userId, String userName) {
System.out.println("UserServiceImpl addUser userId->>"+userId);
}
@Override
public void sayHello(String name) {
System.out.println("你好:"+name);
}
}
public class LogHandler implements InvocationHandler {
private Object targertObject;
public Object newInstance(Object targertObject){
this.targertObject = targertObject;
Class targertClass = targertObject.getClass();
return Proxy.newProxyInstance(targertClass.getClassLoader(),
targertClass.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("調用方法"+method.getName());
Object ret = null;
try {
ret = method.invoke(targertObject, args);
System.out.print("成功調用方法:"+method.getName()+";參數爲:");
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
} catch (Exception e) {
e.printStackTrace();
System.out.print("調用方法:"+method.getName()+"失敗;參數爲:");
for (int i = 0; i < args.length; i++) {
System.out.print(args[i]);
}
}
return ret;
}
}
public class Client {
public static void main(String[] args) {
Service Service = (Service)new LogHandler().newInstance(new UserServiceImpl());
UserService userService = (UserService)new LogHandler().newInstance(new UserServiceImpl());
userService.addUser("001", "centre");
Service.sayHello("centre");
}
}
jdk給目標類提供動態要求目標類必須實現接口,當一個目標類不實現接口時,jdk是沒法爲其提供動態代理的
spring在給某個類提供動態代理時會自動在jdk動態代理和cglib動態代理中動態的選擇。使用cglib爲目標類提供動態代理:須要導入cglib.jar和asm.jar
若是出現asm中的類沒法找到的異常,在java工程中是真的缺乏asm.jar,而在web工程中極可能是asm.jar和spring提供的org.springframework.asm-3.0.4.RELEASE.jar包衝突。
若是一個類繼承了某個類,在子類中沒有一個方法,用cglib生成該子類的動態代理類中將沒有一個方法。
public class CglibProxy implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("調用的方法是:" + method.getName());
Object ret = null;
try {
ret = proxy.invokeSuper(obj, args);
System.out.print("成功調用方法:"+method.getName()+";參數爲:");
for (int i = 0; i < args.length; i++) {
System.out.print(args[i]);
}
} catch (Exception e) {
e.printStackTrace();
System.out.print("調用方法:"+method.getName()+"失敗;參數爲:");
for (int i = 0; i < args.length; i++) {
System.out.print(args[i]);
}
}
return ret;
}
}
public class CglibClient {
public static void main(String[] args) {
cglibUse1();
}
public static void cglibUse1(){
Enhancer enhancer = new Enhancer();
// 設置被代理的類(目標類)
enhancer.setSuperclass(UserServiceImpl.class);
//使用回調
enhancer.setCallback(new CglibProxy());
// 創造 代理 (動態擴展了UserServiceImpl類)
UserServiceImpl my = (UserServiceImpl) enhancer.create();
//my.addUser("001", "centre");
int ret = my.addOperter(15, 22);
System.out.println("返回的結果是:"+ret);
}
}
Jdk動態代理要求被代理的類要實現接口,而cglib不須要,cglib能根據內存中爲其建立子類(代理對象)
Jdk靜態代理能夠理解爲中介(代理類)知道一切,全部的事情由中介來處理,其餘的類完成本身的功能就行了.
jdk動態代理以接口做爲媒介,利用反射創建起代理類和被代理類的關係.
CGLib的具體還有點沒有理解,但願能夠有人補充.
摘自: http://blog.csdn.net/centre10/article/details/6847828