代理模式

1.设计模式原则
  • 单一职责原则:一个类或者一个接口只负责唯一项职责,尽量设计出功能单一的接口;
  • 依赖倒转原则:针对接口编程,依赖于抽象而不依赖于具体;
  • 开放-封闭原则:程序对外扩展开放,对修改关闭;换句话说,当需求发生变化时,我们可以通过添加新模块来满足新需求,而不是通过修改原来的实现代码来满足新需求;
  • 迪米特法则:一个对象应该对其他对象保持最少的了解,尽量降低类与类之间的耦合度;
  • 里氏代换原则:所有引用基类(父类)的地方必须能透明地使用其子类的对象;
  • 接口隔离原则:客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。
2.代理模式
  • 定义:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用;
  • 目的:
    (1)通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性;
    (2)通过代理对象对原有的业务增强。
3.静态代理

这种代理方式需要代理对象和目标对象实现一样的接口。
优点:可以在不修改目标对象的前提下扩展目标对象的功能。
缺点:

  • 冗余。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。
  • 不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。
3.1创建接口Hello

在这里插入图片描述

package org.example.interfc;

public interface Hello {
    public void say();
}
3.2创建目标类HelloWorld
package org.example.stat;

import org.example.interfc.Hello;

public class HelloWorld implements Hello {
    @Override
    public void say() {
        System.out.println("Hello world!!!");
    }
}

3.3创建代理类HelloWorldProxy
package org.example.stat;

import org.example.interfc.Hello;

public class HelloWorldProxy implements Hello {
    private Hello hello;

    public HelloWorldProxy(Hello hello) {
        this.hello = hello;
    }

    @Override
    public void say() {
        System.out.println("hello前=================");
        hello.say();
        System.out.println("hello后=================");
    }
}
3.4测试类

在这里插入图片描述

package org.example;

import org.example.cglib.CglibProxy;
import org.example.cglib.HelloCglib;
import org.example.dynamic.DynamicProxy;
import org.example.interfc.Hello;
import org.example.stat.HelloWorld;
import org.example.stat.HelloWorldProxy;
import org.junit.Test;

public class App 
{

    //静态代理
    @Test
    public void test1(){
        //创建目标对象
        Hello hello = new HelloWorld();
        //代理对象
        HelloWorldProxy helloWorldProxy = new HelloWorldProxy(hello);
        helloWorldProxy.say();
    }

    //动态代理(JDK)
    @Test
    public void test2() {
        //创建目标对象
        Hello hello = new HelloWorld();
        //代理对象
        DynamicProxy dynamicProxy = new DynamicProxy(hello);
        Hello helloProxy = (Hello) dynamicProxy.getProxyInstance();
        helloProxy.say();
    }

    //Cglib代理
    @Test
    public void test3() {
        //创建目标对象
        HelloCglib helloCglib = new HelloCglib();
        //代理对象
        CglibProxy cglibProxy = new CglibProxy(helloCglib);
        HelloCglib helloProxy = (HelloCglib) cglibProxy.getInstance();
        helloProxy.say();
    }
}
3.5查看打印结果

在这里插入图片描述

4.动态代理
  • 动态代理利用了 JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。
  • 动态代理又被称为 JDK 代理或接口代理。静态代理与动态代理的区别主要在:
    (1)静态代理在编译时就已经实现,编译完成后代理类是一个实际的 class 文件
    (2)动态代理是在运行时动态生成的,即编译完成后没有实际的 class 文件,而是在运行时动态生成类字节码,并加载到 JVM 中
    注意:动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。
  • JDK 中生成代理对象主要涉及两个类,第一个类为 java.lang.reflect.Proxy,通过静态方法newProxyInstance 生成代理对象,第二个为 java.lang.reflect.InvocationHandler 接口,通过invoke 方法对业务进行增强
4.1创建代理类DynamicProxy
package org.example.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxy implements InvocationHandler {
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    //通过Proxy获取动态代理的对象
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        doBefore();
        Object object = method.invoke(target, args);
        doAfter();
        return object;
    }

    private void doBefore() {
        System.out.println("Hello before===============");
    }

    private void doAfter() {
        System.out.println("Hello after=================");
    }
}
4.2测试方法

在这里插入图片描述

4.3查看打印结果

在这里插入图片描述

5.Cglib代理
  • 静态代理和动态代理都需要目标对象实现一个接口,对于没有实现接口的目标类,就需要使用Cglib实现代理;
  • 原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理。
5.1创建目标类HelloCglib
package org.example.cglib;

public class HelloCglib {
    public void say() {
        System.out.println("Hello world!!!");
    }
}
5.2创建代理类CglibProxy
package org.example.cglib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    //目标对象
    private Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }

    //为目标对象创建一个代理对象
    public Object getInstance() {
        //使用Enhancer为无接口的类创建代理
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Hello Cglib!!!");
        Object result = methodProxy.invoke(target, objects);
        System.out.println("GoodBye Cglib!!!");
        return result;
    }
}
5.3测试方法

在这里插入图片描述

5.4查看打印结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值