代理模式(MyBatis)——详解

文章目录

  • 一、代理模式
    • 1.1. 代理模式的作用?
    • 1.2 代理模式的分类?
    • 1.3 什么是静态代理?
    • 1.4 什么是动态代理?
    • 1.5 JDK动态代理
    • 1.6 JDK动态代理用到的类和接口:
    • 1.7 CGLib动态代理


一、代理模式

无法访问目标对象,通过代理对象进行访问,而且是增强式的访问。适合业务的扩展。

1.1. 代理模式的作用?

  • a、控制目标对象的访问
  • b、增强功能

1.2 代理模式的分类?

  • a、静态代理
  • b、动态代理(JDK动态代理、CGLib动态代理)

1.3 什么是静态代理?

是代理模式的一种,具备以下特点:

  • a、目标对象和代理对象实现同一个业务接口
  • b、目标对象必须实现接口
  • c、代理对象在程序运行前就已经存在
  • d、能够灵活的进行目标对象的切换,却无法进行功能的灵活处理(使用动态代理来解决此问题)

1.4 什么是动态代理?

代理对象在程序运行的过程中动态在内存构建,可以灵活的进行业务功能的切换

1.5 JDK动态代理

  • a、目标对象必须实现业务接口
  • b、代理对象不需要实现业务接口
  • c、动态代理的对象在程序运行前不存在,在程序运行时动态的在内存中构建
  • d、JDK动态代理灵活的进行功能的切换

1.6 JDK动态代理用到的类和接口:

是使用现在的工具类完成JDK动态实现
a、Proxy类:
有一个方法:Proxy.newProxyInstance(…)专门用来生成动态代理对象。参数:ClassLoader类加载器、 Class<>[] 目标对象实现的所有接口、InvocationHandler 类似于静态代理中代理对象的功能
b、Method类
反射用的类:用来进行目标对象的方法的反射调用。method对象接住我们正在调用的方法。method.invoke();手工调用目标方法。

/**
 - 接口类(业务类)
 */
public interface ActionService {
    void sing();
}
/**
 * 目标对象 刘小备
 */
public class SuperStarLiu implements ActionService {
    @Override
    public void sing() {
        System.out.println("我是刘小备 我在唱歌~~~");
    }
}
/**
 * 目标对象 周小强
 */
public class SuperStarZhou implements ActionService {
    @Override
    public void sing() {
        System.out.println("我是周小强,我在唱歌~~");
    }
}
/**
 * 实现动态代理
 */
public class SuperSatrProxy {
    ActionService target;

    public SuperSatrProxy(ActionService target) {
        this.target = target;
    }

    public Object getAgent(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), this.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("预定时间  !");
                System.out.println("预定场地  !");
                System.out.println("商量费用  !");
                Object obj = method.invoke(target,args);
                System.out.println("结算费用  !");
                return obj;
            }
        });
    }
}

@Test
    public void test1(){
        SuperSatrProxy proxy = new SuperSatrProxy(new SuperStarLiu());
        ActionService agent = (ActionService) proxy.getAgent();
        agent.sing();
    }

此时进行测试 报如下错误:
在这里插入图片描述
java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to com.bjpowernode.service.ActionService at com.bjpowernode.test.MyTest.test1(MyTest.java:12)
排错之后,发现犯了一个低级错误:在动态代理的实现类当中将target写为this
代理模式(MyBatis)——详解_第1张图片
重新运行:
代理模式(MyBatis)——详解_第2张图片

1.7 CGLib动态代理

又称为子类代理,通过动态的在内存中构建子类对象,重写父类的方法进行代理功能的增强。如果目标对象没有实现接口,则只能通过CGLib子类代理来进行功能增强。子类代理是通过字节码框架ASM来实现的。
简易版的CGLib动态代理实现:

/**
 * 目标对象,不用实现接口
 */
public class SuperStarZhou {
    public void sing() {
        System.out.println("我是周小强,我在唱歌~~");
    }
}
public class SubSuperStarZhou extends SuperStarZhou{
    //重写父类的方法,进行增强功能
    @Override
    public void sing() {
        //子类完成代理功能
        System.out.println("预定时间  !");
        //子类完成代理功能
        System.out.println("预定场地  !");
        //子类完成代理功能
        System.out.println("商量费用  !");
        //父类实现自己的业务功能
        super.sing();
        //子类完成代理功能
        System.out.println("结算费用  !");
    }
}
    @Test
    public void test2(){
        SuperStarZhou starZhou = new SubSuperStarZhou();
        starZhou.sing();
    }

代理模式(MyBatis)——详解_第3张图片

注意:
a、被代理的类不能为final,否则报错
b、目标对象的方法如果为final/static,那么就不会执行目标对象额外的业务方法。不能被代理。

你可能感兴趣的:(代理模式,mybatis,java)