版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/love905661433/article/details/84427343
代理模式(Proxy)
- 定义 : 为其他对象提供一种代理, 以控制对这个对象的访问
- 代理对象在客户端和目标对象之间起到中介的作用
- 类型 : 结构型
适用场景
- 保护目标对象
- 增强目标对象
优点
- 代理模式能将代理对象与真实被调用的目标对象分离
- 一定程度上降低了系统的耦合度, 扩展性好
- 保护目标对象
- 增强目标对象
缺点
- 造成系统设计中类的数目增加
- 在客户端和目标对象之间增加了一个代理对象, 会造成一定的性能下降
- 增加了系统的复杂度
扩展
- 静态代理
- 动态代理 : 只能代理实现了接口的类
- CGLib代理 : 通过继承实现的, 所以要注意final关键字
Spring代理选择
-
当Bean中有实现接口时, Spring就会用JDK的动态代理
-
当Bean中没有实现接口时, Spring使用CGLib
-
也可以强制使用CGLib, 增加如下配置即可:
<aop : aspectj-autoproxy proxy-target-class="true"/>
模式角色
-
Proxy :
- 保存一个引用使得代理可以访问实体。若 RealSubject和Subject的接口相同,Proxy会
引用Subject。 - 提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体。
- 控制对实体的存取,并可能负责创建和删除它。
- 控制对实体的存取,并可能负责创建和删除它。
- 保存一个引用使得代理可以访问实体。若 RealSubject和Subject的接口相同,Proxy会
-
Subject : 定义RealSubject 和Proxy 的共用接口,这样就在任何使用 RealSubject的地方都可以使
用Proxy。 -
RealSubject : 定义Proxy所代表的实体
代码实现
静态代理
UML类图:
对应各模块代码:
/**
* @author 七夜雪
* @create 2018-11-24 9:31
*/
public interface Subject {
public void showName();
}
/**
* 被代理类
*
* @author 七夜雪
* @create 2018-11-24 9:30
*/
public class RealSubject implements Subject {
@Override
public void showName() {
System.out.println("被代理类方法---");
}
}
/**
* 代理类
*
* @author 七夜雪
* @create 2018-11-24 9:32
*/
public class Proxy implements Subject {
private RealSubject realSubject = new RealSubject();
@Override
public void showName() {
System.out.println("被代理类方法执行之前执行...");
realSubject.showName();
System.out.println("被代理类方法执行之后执行...");
}
}
测试类 :
/**
* 测试类
*
* @author 七夜雪
* @create 2018-11-24 9:34
*/
public class Client {
public static void main(String[] args) {
Subject subject = new Proxy();
subject.showName();
}
}
测试结果 :
被代理类方法执行之前执行...
被代理类方法---
被代理类方法执行之后执行...
动态代理
这里就以JDK的动态代理为例, 要实现JDK的动态代理, 就需要实现InvocationHandler接口, 下面是具体代码实现:
动态代理类 :
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理
*
* @author 七夜雪
* @create 2018-11-24 9:55
*/
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
public Object bind(){
Class cls = target.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeMethod();
Object invoke = method.invoke(target, args);
afterMethod();
return invoke;
}
private void beforeMethod(){
System.out.println("动态代理 before code");
}
private void afterMethod(){
System.out.println("动态代理 after code");
}
}
Subject接口 :
/**
* @author 七夜雪
* @create 2018-11-24 9:31
*/
public interface Subject {
public void showName();
}
Subject接口的两个实现类, 即被代理的类 :
/**
* 被代理类
*
* @author 七夜雪
* @create 2018-11-24 9:30
*/
public class RealSubject1 implements Subject {
@Override
public void showName() {
System.out.println("被代理类方法1---");
}
}
/**
* 被代理类
*
* @author 七夜雪
* @create 2018-11-24 9:30
*/
public class RealSubject1 implements Subject {
@Override
public void showName() {
System.out.println("被代理类方法2---");
}
}
测试代码 :
/**
* 测试类
*
* @author 七夜雪
* @create 2018-11-24 9:34
*/
public class Client {
public static void main(String[] args) {
Subject proxy1 = (Subject) new DynamicProxy(new RealSubject1()).bind();
Subject proxy2 = (Subject) new DynamicProxy(new RealSubject2()).bind();
proxy1.showName();
proxy2.showName();
}
}
测试结果 :
动态代理 before code
被代理类方法1---
动态代理 after code
动态代理 before code
被代理类方法2---
动态代理 after code
本文参考:
慕课网<java设计模式精讲 Debug 方式+内存分析>课程
四人帮<设计模式>