設計模式之代理模式
靜态代理
package designpattern.proxy;
public class staticsubject implements Subject {
private ConcretSubject concretSubject;
@Override
public void request() {
concretSubject = new ConcretSubject();
System.out.println("前置方法ss");
concretSubject.request();
System.out.println("後置方法ss");
}
}
建立一個代理類同樣實作接口,在代理類中調用被代理的類的方法就實作了靜态代理。
動态代理
靜态代理我們需要為每一個代理的類建立一個代理,這會大大的增加代碼量,是以可以使用動态代理。
在動态代理中不需要手動建立代理類,隻需要編寫一個動态處理器,真正的代理對象有JDK在運作時為我們動态的建立。
JDK動态代理
第一種方法,建立一個實作InvocationHandler的類
定義一個接口
package designpattern.proxy;
public interface Subject {
void request();
}
被代理的類
package designpattern.proxy;
public class ConcretSubject implements Subject {
@Override
public void request() {
System.out.println("請求");
}
}
代理方法
package designpattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置方法");
Object o = method.invoke(target, args);
System.out.println("後置方法");
return o;
}
public Object getInstance(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
實作
package designpattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class client {
public static void main(String[] args) {
JDKProxy proxy = new JDKProxy();
Subject instance = (Subject) proxy.getInstance(new ConcretSubject());
instance.request();
o.request();
}
}
第二種方法:直接在Proxy.newProxyInstance()第三個參數中對方法進行增強。
package designpattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class client {
public static void main(String[] args) {
Subject o = (Subject) Proxy.newProxyInstance(ConcretSubject.class.getClassLoader(), ConcretSubject.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置方法11");
Object o = method.invoke(new ConcretSubject());
System.out.println("後置方法22");
return o;
}
});
o.request();
}
}
CGlib動态代理
JDK實作動态代理需要實作類通過接口定義業務方法,對于沒有接口的類,要想實作動态代理,就需要使用CGLib。
CGLib采用位元組碼技術,通過位元組碼技術為一個類建立一個子類,并在子類中采用方法攔截的技術攔截所有父類方法調用,順勢植入橫切邏輯。因為采用的繼承,是以不能對final修飾的類進行代理。
package designpattern.proxy;
public class cgclient {
public static void main(String[] args) {
CGProxy proxy = new CGProxy();
Subject target = (Subject) proxy.getTarget(new ConcretSubject());
target.request();
}
}
package designpattern.proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGProxy implements MethodInterceptor {
private Object target;
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("前置方法123");
Object ob = method.invoke(target, args);
System.out.println("後置方法123");
return ob;
}
public Object getTarget(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
}