代理模式
代理模式属于结构型的模式,通过代理对象来访问目标对象,即可以扩展目标对象的功能,比如日志记录,或者是安全检查,我们常用的AOP面向切面编程是属于一种代理模式。
代理模式的形式:静态代理,动态代理(JDK 代理),cglib代理(基于内存实现)
代理模式的角色
- 客户端:通过代理对象访问目标对象
- 代理对象
- 目标对象
静态代理
代理对象与目标对象都要实现同一个接口或者父类,客户端通过代理对象来访问目标对象
案例
代码
抽象父类接口
/**
* 抽象父类接口
*
* @author: Hui
**/
public interface ITeacher {
public void teach();
}
目标对象
/**
* 目标对象
*
* @author: Hui
**/
public class TeacherTarget implements ITeacher{
@Override
public void teach() {
System.out.println(" 老师开始授课了 ~~~~");
}
}
代理对象
/**
* 代理对象
*
* @author: Hui
**/
public class TeacherProxy implements ITeacher{
private ITeacher iteacher;
public TeacherProxy(ITeacher teacher) {
this.iteacher = teacher;
}
@Override
public void teach() {
System.out.println("代理对象 开始");
iteacher.teach();
System.out.println("代理对象 结束");
}
}
客户端使用
/**
* 客户端
*
* @author: Hui
**/
public class Client {
public static void main(String[] args) {
TeacherTarget teacherTarget = new TeacherTarget();
TeacherProxy teacherProxy = new TeacherProxy(teacherTarget);
teacherProxy.teach();
}
}
输出结果
动态代理
又称为 JDK 代理,通过JDK 反射的包来实现。
案例
代码
抽象父类与实现类
/**
* 抽象父类
*
*/
public interface ITeacher {
void teach();
}
/**
* 目标对象
*
* @author: Hui
**/
public class TeacherDao implements ITeacher{
@Override
public void teach() {
System.out.println("老师授课中 ~~~~");
}
}
代理工厂
/**
* 代理工厂
*
* @author: Hui
**/
public class ProxyFactory {
private Object target;
//构造器
public ProxyFactory(Object target){
this.target = target;
}
//获取代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始代理");
Object resultVal = method.invoke(target, args);
System.out.println("结束代理");
return resultVal;
}
});
}
}
客户端
/**
* 客户端
*
* @author: Hui
**/
public class Client {
public static void main(String[] args) {
ITeacher teacherDao = new TeacherDao();
// 创建代理对象
ITeacher proxyFactory = (ITeacher) new ProxyFactory(teacherDao).getProxyInstance();
proxyFactory.teach();
}
}
cglib代理
cglib代理是可以不急于抽象父类或者抽象接口。
使用的代理工厂实现methodIntecetor,重写 intecetor方法就可以了。
引入依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
目标对象
/**
* 目标对象
*
* @author: Hui
**/
public class TeacherTarget {
public void teach()
{
System.out.println("老师授课中...");
}
}
代理工厂
/**
* 代理工厂
*
* @author: Hui
**/
public class ProxyFactory implements MethodInterceptor {
private Object target;
public Object getProxyInstance(Object obj){
this.target = obj;
//1.创建工具类
Enhancer enhancer = new Enhancer();
//2.设置父类
enhancer.setSuperclass(obj.getClass());
//3.设置回调函数
enhancer.setCallback(this);
//4.创建子类对象,即代理对象
Object proxyObj = enhancer.create();
//返回代理对象
return proxyObj;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib代理开始");
Object resultVal = method.invoke(target, objects);
System.out.println("cglib代理结束");
return resultVal;
}
}
客户端
/**
* 客户端
*
* @author: Hui
**/
public class Client {
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory();
TeacherTarget teacherProxy =(TeacherTarget) proxyFactory.getProxyInstance(new TeacherTarget());
teacherProxy.teach();
}
}