设计模式——代理模式
知识点:静态代理和动态代理
参考博客:https://www.cnblogs.com/daniels/p/8242592.html
https://blog.csdn.net/familyshizhouna/article/details/78905997
一:什么是代理模式
代理模式是给某个对象提供一个代理对象,由代理对象调用原对象的方法,类似我们生活中的中介,经纪人的角色,本人不直接去做,找一个人代替我们去做一些事情。
二:使用代理模式的好处
a.中介隔离作用:当我们不想直接调用一个对象时,代理对象可以起一个中介隔离的作用,被代理对象和代理对象都实现相同的接口
b.遵循开闭原则:我们可以通过代理类,在被代理类功能前后,加入一些公共服务,比如缓存,日志等,而不用修改原被代理类
三:代理模式的分类
按创建代理的时间分类可以分为:静态代理和动态代理
静态代理是代码创建后编译,运行之前,代理类的.class文件就已经创建了;
动态代理:是在程序运行时,通过反射机制动态创建代理对象的(另一篇博客简略地介绍Java中的反射:https://www.cnblogs.com/shuaifing/p/10863645.html)
(1)静态代理
//代理模式(静态代理)
//测试类
public class StaticProxy {
public static void main(String[] args) {
Object obj=new ProxyObject();
obj.action();
}
}
//公共接口
interface Object{
void action();
}
//代理类
class ProxyObject implements Object{
Object obj;
public ProxyObject(){
System.out.println("代理类构造方法创建被代理类");
obj=new ObjectImp();
}
@Override
public void action() {
System.out.println("代理类执行被代理类中的方法");
obj.action();
}
}
//被代理类
class ObjectImp implements Object{
@Override
public void action() {
System.out.println("被代理类输出的内容!");
}
}
运行结果:
(2)动态代理
当有多个类要代理的话,手动创建多个代理对象比较麻烦,代码冗余,动态产生代理对象的话,代码更加灵活,方便
//动态代理,反射是动态语言的关键
//测试类
public class DynamicProxy {
public static void main(String[] args) {
//1.被代理类的对象
RealSubject realSubject=new RealSubject();
//2.创建一个实现InvocationHandler接口类的对象
MyInvocationHandler handler=new MyInvocationHandler();
//3.调用blind()方法,动态返回一个实现了跟被代理类所实现接口的代理对象
Object obj=handler.blind(realSubject);
Subject subject=(Subject) obj;//subject是代理类对象
subject.action();//代理类对象调用action(),会转到对InvocationHandler接口实现类的invoke()方法调用
//增加另一个 ObjectImp的被代理对象,返回相应的代理对象
ObjectImp objIml=new ObjectImp();
com.kdgc.interfacetest.Object proxyObject= (com.kdgc.interfacetest.Object)handler.blind(objIml);
proxyObject.action();
}
}
//公共接口
interface Subject{
void action();
}
//被代理类
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("被代理类要执行的方法!");
}
}
class MyInvocationHandler implements InvocationHandler{
Object obj;//实现了接口的被代理对象的声明
//1.给被代理对象实例化 2.返回一个代理类的对象
public Object blind(Object obj){
this.obj=obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
//当通过代理类的对象发起对被重写方法的调用时,会转化为对下面的invoke方法的调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object val=method.invoke(obj,args);
return val;
}
}
运行结果:
(3)补充:动态代理与AOP
在固定的代码的位置,动态地调用不同对象的方法
//测试类
public class AOPTest {
public static void main(String[] args) {
Man man = new Man();
Person person = (Person) MyProxy.getProxyInstance(man);
person.drink();
person.eat();
}
}
//公共接口
interface Person{
void eat();
void drink();
}
//被代理类
class Man implements Person{
@Override
public void eat() {
System.out.println("吃东西!");
}
@Override
public void drink() {
System.out.println("喝水!");
}
}
//固定的方法
class ChangelessMethodUtil{
public void method1(){
System.out.println("===========方法1==========");
}
public void method2(){
System.out.println("============方法2===========");
}
}
class MyInvocationHanlder implements InvocationHandler{
Object obj;//代理类的声明
public void setObject(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ChangelessMethodUtil changelessMethodUtil=new ChangelessMethodUtil();
changelessMethodUtil.method1();
method.invoke(obj,args);
changelessMethodUtil.method2();
return null;
}
}
class MyProxy{
//动态创建一个代理类的对象
public static Object getProxyInstance(Object obj){
MyInvocationHanlder hanlder=new MyInvocationHanlder();
hanlder.setObject(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),hanlder);
}
}
运行结果: