模式介绍
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
模式优点
1、职责清晰。
2、高扩展性。
模式缺点
1、由于在客户端和真实对象之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景
1、远程代理。
2、虚拟代理。
3、保护(Protect or Access)代理。
4、Cache代理。
5、防火墙(Firewall)代理。
6、同步化(Synchronization)代理。
7、智能引用(Smart Reference)代理。
系统建模
1、下面分别实现三种代理模式。
系统实现
静态代理:代理模式中最简单的一种实现方式。
/**
* 老师接口
*/
public interface ITeacher {
public void teach();
}
/**
* 老师实现类
*/
public class Teacher implements ITeacher {
@Override
public void teach(){
System.out.println("今天我们学习如何打野更有效率!");
}
}
/**
* 老师代理
*/
public class TeacherProxy {
private ITeacher teacher;
public TeacherProxy(ITeacher teacher){
this.teacher = teacher;
}
public void teach(){
System.out.println("代理开始了!");
teacher.teach();
System.out.println("代理结束了!");
}
}
/**
* 客户端
*/
public class Client {
public static void main(String args[]){
TeacherProxy proxy = new TeacherProxy(new Teacher());
proxy.teach();
}
}
结果:
代理开始了!
今天我们学习如何打野更有效率!
代理结束了!
动态代理:动态代理又称JDK代理或接口代理,被代理对象必须实现接口。
/**
* 老师接口
*/
public interface ITeacher {
public void teach();
}
/**
* 老师实现类
*/
public class Teacher implements ITeacher {
@Override
public void teach(){
System.out.println("今天我们学习如何打野更有效率!");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理工厂
*/
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
public Object getProxyInstance(){
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
return Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK代理开始!");
Object returnObject = method.invoke(target, args);
return returnObject;
}
});
}
}
/**
* 客户端
*/
public class Client {
public static void main(String args[]){
ITeacher teacher = new Teacher();
ITeacher proxyTeacher = (ITeacher)new ProxyFactory(teacher).getProxyInstance();
proxyTeacher.teach();
}
}
结果:
JDK代理开始!
今天我们学习如何打野更有效率!
Cglib代理:针对代理的类, 动态生成一个子类, 然后子类覆盖代理类中的方法, 如果是final修饰的方法,则不会被重写。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency
/**
* 老师类
*/
public class Teacher {
public void teach(){
System.out.println("今天我们学习如何打野更有效率!");
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/*
* 代理工厂
*/
public class ProxyFactory implements MethodInterceptor{
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxy() {
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass());
en.setCallback(this);
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Cglib代理开始了!");
Object returnValue = proxy.invokeSuper(obj, args);
return returnValue;
}
}
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
ProxyFactory teacherProxy = new ProxyFactory(new Teacher());
Teacher teacher = (Teacher)teacherProxy.getProxy();
teacher.teach();
}
}
结果:
Cglib代理开始了!
今天我们学习如何打野更有效率!