代理模式(结合SpringAop底层实现)

Proxy代理模式

代理模式基本概念:为其他对象提供一个代理来控制这个的访问。

主要解决的问题:直接访问对象时所带来的问题。

代理类: 负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理

举个栗子(=.=)

开始接触spring框架的时候,必然的要去了解 IOC 和 AOP,其中AOP的底层实现原理就是动态代理。以此为切入点,通过对AOP底层实现的理解,初识代理模式。

1、静态代理实现AOP,首先来一波简单代码①

//目标对象的接口
public interface IWorkDao {
    void work();
}

//实现类
public class WorkDaoImpl implements IWorkDao {
    @Override
    public void work() {
        System.out.println("这里是目标对象WorkDao的实现类");
    }
}

//增强类:一般给类方法添加事务控制或者性能检测
public class TransactionManager {

    public void beginTransation(){
        System.out.println("start...");
    }

        //切割线------
        //...业务逻辑代码
        //切割线------

       public void endTransation(){
        System.out.println("over...");
    }
}

目标对象增加的过程产生代理类

//代理对象持有被代理对象的一个接口public class WorkDaoProxy implements IWorkDao {    //主角:目标对象    IWorkDao workDao;    //配角:增强对象    TransactionManager tx;    //来一个构造器    public WorkDaoProxy(IWorkDao workDao, TransactionManager tx) {        this.workDao = workDao;        this.tx = tx;    }    //将增强添加到目标对象(织入)    @Override    public void work() {        tx.beginTransation();//非业务代码        workDao.work(); //业务代码        tx.endTransation();//非业务代码,横向切割体现出来了有木有    }}

//测试类
public class Test {
    public static void main(String[] args) {
        //目标对象
        IWorkDao workDao = new WorkDaoImpl();

        //增强
        TransactionManager tx = new TransactionManager();

        //代理对象
        WorkDaoProxy workDaoProxy = new WorkDaoProxy(workDao,tx);

        //代理对象调用目标方法
        workDaoProxy.work();
    }
}

这里存在一个问题,要是我创建其他的目标对象接口比如ISleepDao或者修改当前类方法名,这不又得重新创建一个代理类或者修改?好麻烦有木有,所以就有以下方案:

2、基于jdk动态代理实现AOP(基于InvocationHandler接口模式),代码①省略

//代理类
public class ProxyHandle implements InvocationHandler {
    //目标对象(不用知道具体的目标对象是谁,好神秘)
    Object target;

    //增强
    TransactionManager tx;

    //构造器(用于实例化handle)
    public ProxyHandle(Object target, TransactionManager tx) {
        this.target = target;
        this.tx = tx;
    }

    /**
    * 织入
    * @param proxy 
    * @param method 
    * @param args 参数列表
    * @return
    * @throws Throwable
    */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        tx.beginTransation();
        Object obj = method.invoke(target, args);
        tx.endTransation();
    return obj;
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
    //目标对象
    IWorkDao workDao = new WorkDaoImpl();

    //增强
    TransactionManager tx = new TransactionManager();

    //获得handle(构造器开辟内存空间用于存放目标对象和增强对象)
    ProxyHandle handle = new ProxyHandle(workDao,tx);

     //生成代理对象(传入handle,利用反射获得目标对象和增强)
    IWorkDao workDaoProxy = (IWorkDao) Proxy.newProxyInstance(workDao.getClass().getClassLoader(),                             workDao.getClass().getInterfaces(), handle);

    //代理对象调用目标方法
    workDaoProxy.work();
    }
}

解决了每创建一个目标对象必须创建一个代理类的问题,JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,但是,JDK中所要进行动态代理的类必须要实现一个接口(如上面的:Object target 的接口),也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。

3、基于cglib动态代理实现AOP,首先要导入cglib的jar包,继续代码①省略

    //代理类
    public class CglibDynInterceptor implements MethodInterceptor{
    //要代理的原始对象(抛弃你了)
    //private Object object;

    private Enhancer enhancer = new Enhancer();
    private TransactionManager tx;

    public CglibDynInterceptor(TransactionManager tx) {
    this.tx = tx;
}

    //创建子类
    public Object getProxy(Class cls){
    enhancer.setSuperclass(cls); //设置代理对象
    enhancer.setCallback(this); //回调MethodInterceptor接口方法拦截(类似于JDK中的            InvocationHandler接口)
    //通过字节码技术动态创建子类
    return enhancer.create();
}

    /**
     * object:由CGLib动态生成的代理类实例
    * method:增强方法引用
    * args:参数值列表
    * methodProxy:生成的代理类对方法的代理引用
    */
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy)
    throws Throwable {
     tx.beginTransation();
     //拦截父类方法(调用代理类实例上的proxy方法的父类方法)
     Object result = methodProxy.invokeSuper(object, args);
     tx.endTransation();
     return result;
    }
}

    //测试类 
    public class Test {
    public static void main(String[] args) {
    //增强
    TransactionManager tx = new TransactionManager();
    //创建代理类
    CglibDynInterceptor proxy = new CglibDynInterceptor(tx);
    //通过反射创建代理对象(子类)
    IWorkDao workDaoProxy = (IWorkDao) proxy.getProxy(IWorkDao.class);
    workDaoProxy.work();
    }
}

使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

Enhancer允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作(解决jdk动态代理中每创建一个代理类必须要实现接口)

另外:Callback接口是一个空接口,没有任何契约方法,它只表示这是一个回调。

以上是个人结合SpringAop底层实现原理去理解代理模式,不足之处还请谅解~

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP底层实现原理主要是基于动态代理。Spring AOP通过使用代理模式,在运行时动态地为目标对象生成一个代理对象,然后通过代理对象来完成对目标对象的方法增强。 具体实现步骤如下: 1. 定义切面类:切面类是一个普通的Java类,用于定义切点和增强逻辑。切点是指确定在何处应用增强逻辑的表达式。增强逻辑是指在切点处插入的具体行为,如日志记录、事务管理等。 2. 配置切面:在Spring配置文件中,通过<aop:aspect>标签配置切面类,并使用<aop:pointcut>标签定义切点表达式。 3. 创建代理对象:在Spring容器启动时,会解析配置文件并扫描所有的Bean对象。当Spring发现某个Bean对象需要进行AOP增强时,会为该对象动态地创建一个代理对象。代理对象可以通过JDK动态代理或者CGLIB动态代理来创建。 4. 方法调用时的增强逻辑:当通过代理对象调用方法时,实际上是调用了代理对象中的方法。在代理对象的方法中,会根据切点表达式判断是否需要插入增强逻辑。如果需要插入增强逻辑,则会在方法的前后或者异常抛出时执行相应的增强操作。 总结起来,Spring AOP底层实现原理是通过动态代理,在运行时为目标对象生成代理对象,并在代理对象中实现对目标对象方法的增强。这个过程是在Spring容器启动时进行的,通过配置文件中的切面定义和切点表达式,确定增强逻辑的插入位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值