常用设计模式--代理模式
代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。
代理又分为静态代理和动态代理,我们一般指的都是动态代理。
在 Java 中,动态代理有两种:JDK 动态代理、cglib 动态代理
JDK代理
接口
public interface HelloWorld {
void sayHelloWorld();
}
实现类
public class HelloWorldImpl implements HelloWorld{
@Override
public void sayHelloWorld() {
System.out.println("Hello world");
}
}
代理类
public class JdkProxyExample implements InvocationHandler {
/*
这个就是我们要代理的真实对象
*/
private Object target = null;
//返回代理类的一个实例,返回后的代理类可以当作被代理类使用
/*
static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)
第一参数:类加载器
第二参数:创建袋里实例需要的一组接口
第三参数:整合了业务逻辑和横切逻辑的编织器对象
*/
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
/*
第一个参数proxy一般是指代理类,
method是被代理的方法,如上例中的request(),
args为该方法的参数数组。
这个抽象方法在代理类中动态实现。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调度真实对象之前的服务");
Object obj = method.invoke(target, args);
System.out.println("在调度真实对象之后的服务");
return obj;
}
}
测试类
public class TestMain {
public static void main(String[] args) {
JdkProxyExample jdk = new JdkProxyExample();
//将代理的实例传入,返回真实的代理对象
HelloWorld proxy = (HelloWorld) jdk.bind(new HelloWorldImpl());
//真实代理对象调用方法
proxy.sayHelloWorld();
}
}
结果
可以看出,jdk 代理的重点在于 Proxy.newProxyInstance() 方法和 invoke() 方法。
代理类继承了Proxy类并且实现了要代理的接口,由于java不支持多继承,所以JDK动态代理不能代理类,只能代理接口。
cglib代理
使用 cglib 代理需要单独导入相应的 jar包
被代理类
public class SayHello {
public void sey(String name){
System.out.println("Hello "+ name);
}
}
代理类
public class CglbProxyExample implements MethodInterceptor {
public Object getProxy(Class cls){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method,
Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真实对象前");
Object result = methodProxy.invokeSuper(obj, objects);
System.out.println("调用真实对后");
return result;
}
}
测试类
public class TestCglibMain {
public static void main(String[] args) {
CglbProxyExample cglib = new CglbProxyExample();
SayHello proxy = (SayHello) cglib.getProxy(SayHello.class);
proxy.sey("张三");
}
}