Spring-AOP

AOP简介

  • 在软件开发行业,AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程
  • 通过 预编译 的方式和运行期间,使用动态代理的方式来实现程序功能的统一维护的一种技术
  • AOP 是 OOP (面向对象)的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是 函数式 编程的一种衍生范型
  • 利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑的各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

开发中存在的问题

  • 假如你需要在某一个功能之前加一个功能
  • 你自己定义一个方法,然后在显示的手动调用
  • 每个方法都要的话不都需要写一次

  • 采用 纵向继承 的方式来进行改进

  • AOP采用了 横向抽取 的机制取代了传统的 纵向继承
  • 不破坏原有的类,生成一个新的代理类,在原来类的基础上进行增强
  • 可以随时添加,随时取消添加的功能

JDK动态代理

  • 新建一个 GoodsDao 接口
  • 定义一个 save 接口规范代码如下:
/**
 * @author: BNTang
 **/
public interface GoodsDao {
    void save();
}
  • 创建一个实现类 GoodsDaoImpl 实现 GoodsDao 接口
  • 并且实现当中的 save 方法,代码如下:
/**
 * @author: BNTang
 **/
public class GoodsDaoImpl implements GoodsDao {
    @Override
    public void save() {
        System.out.println("save goods");
    }
}
  • 新建一个JDK代理类 JDKProxy
  • 在当中定义一个 createProxy 方法,代码如下:
/**
 * @author: BNTang
 **/
public class JDKProxy {
    private GoodsDao goodsDao;

    public JDKProxy(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

    public GoodsDao createProxy() {
        GoodsDao goodsDaoProxy = (GoodsDao) Proxy.newProxyInstance(goodsDao.getClass().getClassLoader(),
                goodsDao.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if ("save".equals(method.getName())) {
                            System.out.println("permission check");
                            return method.invoke(goodsDao, args);
                        }
                        return method.invoke(goodsDao, args);
                    }
                });
        return goodsDaoProxy;
    }
}
  • 测试类代码如下:
/**
 * @author: BNTang
 **/
public class GoodsDaoTest {
    @Test
    public void Demo() {
        GoodsDao goodsDao = new GoodsDaoImpl();

        JDKProxy jdkProxy = new JDKProxy(goodsDao);
        GoodsDao proxyBean = jdkProxy.createProxy();
        proxyBean.save();
    }
}
  • 输出结果如下:
permission check
save goods

CgLib动态代理

  • CgLib 是一个第三方开源的第三方库
  • 可以动态的添加类的属性和方法
  • 在 Spring 的核心包当中已经引入了 cglib

  • CgLib 采用的是 继承的方式 来创建的代理对象
  • 创建 CgLibProxy 类,代码如下:
/**
 * @author: BNTang
 **/
public class CgLibProxy {

    private GoodsDao goodsDao;

    public CgLibProxy(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

    public GoodsDao createProxy() {
        // 1.创建 CgLib 核心类
        Enhancer enhancer = new Enhancer();

        // 2.采用的是继承的方式来创建的代理对象
        enhancer.setSuperclass(goodsDao.getClass());

        // 3.设置回调方法
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                if ("save".equals(method.getName())) {
                    System.out.println("permission check");
                    return methodProxy.invokeSuper(proxy, args);
                }
                return methodProxy.invokeSuper(proxy, args);
            }
        });

        // 4.创建代理对象
        return (GoodsDao) enhancer.create();
    }
}
  • 测试类代码如下:
/**
 * @author: BNTang
 **/
public class GoodsDaoTest {
    @Test
    public void Demo() {
        GoodsDao goodsDao = new GoodsDaoImpl();

        CgLibProxy cgLibProxy = new CgLibProxy(goodsDao);
        GoodsDao proxy = cgLibProxy.createProxy();
        proxy.save();
    }
}

Spring的AOP简介

  • AOP 的思想,最早是由AOP联盟组织提出的
  • 使用这种思想最好的框架是 Spring

AspectJ

  • Spring 的 AOP有自己的实现方式
  • 但是自己实现的方式非常的繁琐
  • AspectJ 是一个 AOP框架
  • Spring 放弃了自己传统的方式,也就是自己实现的方式
  • 引入 AspectJ 作为自身的 AOP来进行开发
posted @ 2020-10-05 08:18  BNTang  阅读(81)  评论(0编辑  收藏  举报