模式介绍
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
静态代理
代理模式中最简单的一种实现方式。
/**
* 老师接口
*/
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 代理或接口代理,被代理对象必须实现接口。
1、优点:能够以工厂模式生成对应的代理;目标代码改变代理不需要进行改变。
2、缺点:需要代理的目标类,一定要实现接口才行,一定要实现 java.lang.reflect.InvocationHandler 接口。
/**
* 老师接口
*/
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 修饰的方法,则不会被重写。
1、优点:能够以工厂模式生成对应的代理;目标代码改变代理不需要进行改变;需要代理的目标类,不一定要实现接口才行。
2、缺点:一定要实现 net.sf.cglib.proxy.MethodInterceptor 接口。
<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代理开始了!
今天我们学习如何打野更有效率!