设计模式之代理模式
静态代理
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();
}
}