浅谈Spring之AOP

1.AOP是什么

AOP:全称(Aspect Oriented Programming)面向切面编程。
AOP是一种编程思想,指的是在程序运行期间,将某段代码动态切入到指定方法指定位置进行运行的编程方式。那么这句话是在说什么呢?


假设我们想实现转账功能,转账需要事务管理。我们第一时间会想到在转账的过程中进行事务管理(如开启事务、回滚事务、提交事务),而且都将转账业务和事务管理都封装到一起。
那么下一步我们可能会想到将事务管理封装到一个类中,当需要事务管理的时候,我们手动去调用。这样的确简化了代码,但是这意味着我们执行一个事务都得去手动调用事务管理的方法。


AOP的思想其实就是将事务管理的代码动态切入到转账业务中。
这时候事务管理就是一个切面,面向切面编程就是将切面注入到切入点,将事务管理注入到转账方法中,当执行转账方法中,会为转账方法进行一个事务管理。
这样就可以看出AOP的好处

  1. 在程序运行期间,在不修改源码的情况下对方法进行功能增强
  2. 逻辑清晰,开发核心业务的时候,不必关注增强业务的代码
  3. 减少重复代码,提高开发效率,便于后期维护

2.AOP底层怎么实现动态切入

 一句话就是底层用了动态代理

动态代理的思想就是在不改变目标类的代码前提下,对目标类的方法进行功能增强
也就是不改变转账业务的前提下,对转账进行事务管理,也就是功能的增强。

3.AOP的两种动态代理方式

①JDK动态代理(基于接口实现)

实现代码如下:

public class JDKProxyFactory {
    public static Object getProxy(final Class clazz){
        Object proxy = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
         /**
         * newProxyInstance:创建代理对象
         * 参数:
         *      ClassLoader loader: 加载目标类的类加载器
         *      Class<?>[] interfaces:目标类所实现的接口类型(用于做为生成代理对象的模板)
         *      InvocationHandler h:它是代理对象的功能。
         */
         //此方法在代理对象调用任何方法时都会执行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object o = null;
                try {
                    MyAspect.begin();
                    o = method.invoke(clazz.newInstance(), args);
                    MyAspect.commit();
                } catch (Exception e) {
                    MyAspect.rollback();
                    e.printStackTrace();
                } finally {
                    MyAspect.close();
                }
                return o;
            }
        });
        return proxy;
    }

}
为什么JDK动态代理是基于接口呢?

原因如下:
1、生成的代理类继承了Proxy,由于java是单继承,所以只能实现接口去生成对应的代理对象。
2. 可以在生成代理对象的代码中看到Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() { }中参数有一个接口。

②Cglib动态代理(基于子类实现)

实现代码如下:

    public static Object getProxy(final Class clazz){
        //创建一个代理工具类
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(clazz);
        //设置回调方法(方法增强)
        enhancer.setCallback(new MethodInterceptor() {
            //o:代理对象本身的引用
            //method:代理对象调用的方法
            //objects:方法的参数
            //methodProxy:代理对象调用的父类方法(一般不用)
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object oo = null;
                try {
                    MyAspect.begin();
                    oo = method.invoke(clazz.newInstance(),objects);
                    MyAspect.commit();
                } catch (Exception e) {
                    MyAspect.rollback();
                    e.printStackTrace();
                } finally {
                    MyAspect.close();
                }
                return oo;
            }
        });
        //创建代理对象
        Object obj = enhancer.create();
        return obj;
    }

cdlib动态代理是使用第三方 cglib库,所以要先导入jar包,Maven项目可以在pom.xml文件中添加spring-core-5.1.6.RELEASE依赖。

为什么Cglib动态代理是基于子类呢?

因为cglib实现动态代理方式是对指定的类生成一个子类,覆盖其中的所有方法,也因此代理类或方法不能声明称final的。

4.怎么选择JDK动态代理和Cglib动态代理

如果有接口,默认就会采用jdk动态代理
没有接口,就采用cglib动态代理的方式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值