复习整理的DAY31_代理模式与SpringAOP

什么是代理模式?

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

代理模式分类:

静态代理与动态代理,动态代理两者实现方式——JDK动态代理,CGLIB动态代理。

静态代理:在程序运行前,代理类的字节码文件就存在。

动态代理:程序运行时动态创建代理类。

什么是代理类?

为对象提供一种代理以控制对这个对象的访问。

静态代理

比如我们存取的时候需要验钞机,通过它,合格了,才能将前存进银行。这个验钞机就好比代理类,我们不能直接接触内部,需要经过中间的验钞机,才能把我们的钱存进去。

复习整理的DAY31_代理模式与SpringAOP

 具体实现:

复习整理的DAY31_代理模式与SpringAOP

public interface IBank {
  public void save();
}
public class Bank implements IBank{
  @Override
  public void save() {
    System.out.println("Bank.save()");
  }
}

public class Proxy implements IBank{
  private Bank bank;
  
  public Proxy(Bank bank) {
    this.bank = bank;
  }
  
  @Override
  public void save() {
    // 判断是否合法
    System.out.println("Proxy.save.before");
    bank.save();
    System.out.println("Proxy.save.after");
  }
}

public class Money {
  public static void main(String[] args) {
    Bank bank = new Bank();
    IBank proxy = new Proxy(bank);
    proxy.save();
  }
}

 为什么要让代理类(验钞机)和目标对象(银行)访问同一个接口(IBank)?

为了让客户端(钱)访问的时候,代理类和目标对象的行为保持一致,这是一种对目标对象的保护。

总结代理类的作用:实现与目标对象相同的接口,可以用来代替目标对象;保存一个目标对象的引用,在需要时调用目标对象对应的方法;控制对目标对象的访问。

总结静态代理优点:可以在不修改目标对象的前提下,对目标对象进行功能扩展。

这一点就像是古代的摄政王,有些时候以皇帝的名义出发,做了很多事,不管好坏,在底层老百姓眼里,只要皇帝没驾崩,这些都是皇帝的旨意。

静态代理缺点:有一个目标对象就要有一个代理对象,会产生很多代理对象;而一旦接口增加了方法,代理类和目标对象都要去维护,繁琐。

动态代理:这里主要说JDK动态代理

JDK动态代理: 使用JDK的反射机制,创建代理类的对象。

注:不需要自己写代理对象,但还是需要实现接口;代理对象,是利用JDKAPI动态地在内存中构建。

具体实现:

public class ProxyFactory {
    /**
     * 使用动态代理生成代理对象
     * @param target 目标对象(还是要实现一个接口)
     * @return 代理对象
     */
    public static Object getProxyInstance(Object target) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(), // 目标对象使用的类加载器
                target.getClass().getInterfaces(), // 目标对象实现的接口
                new InvocationHandler() { // 事件处理器
                    // 这个invoke方法就相当于代理类MiShu里面的qianzi()方法
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // Object proxy 代理对象
                        // Method method 调用的方法
                        // Object[] args 调用的方法的参数
                        System.out.println("ProxyFactory.invoke.before");
                        Object returnValue = method.invoke(target, args);
                        System.out.println("ProxyFactory.invoke.after");
                        return returnValue;
                    }
                }
        );
    }
}

public interface IBank {
  public void save();
}
public class Bank implements IBank{
  @Override
  public void save() {
    System.out.println("Bank.save()");
  }
}

public class Money {
  public static void main(String[] args) {
    Bank target = new Bank();
    IBank proxy = (IBank)ProxyFactory.getProxyInstance(target);
    proxy.save();
  }
}

JDK动态代理的优点:不需要自己写代理类

JDK动态代理的缺点:只能实现对接口方法的增强,不能实现对接口类的动态代理。

针对JDK动态代理的缺点,如果想要实现对接口类的动态代理,可以使用CGLIB动态代理。

在Spring的AOP编程中,如果加入容器的目标对象有实现接口,用JDK代理;如果目标对象没有实现接口,用CGLIB代理。

上一篇:npm install --save 、--save-dev 、-D、-S 的区别


下一篇:Photoshop 入门教程「5」如何使用“保存”命令?