木木的Java知识整理——Spring AOP

Spring AOP

  • 一、AOP概述
    • 1.1 AOP概述
    • 1.1 AOP的术语
  • 二、AOP的底层实现
    • 2.1 JDK的动态代理
    • 2.2 CGLIB的动态代理
    • 2.3 代理知识的总结

一、AOP概述

1.1 AOP概述

AOP : Aspect Oriented Programing 面向切面编程
AOP采用横向抽取机制(代理机制), 取代了传统纵向继承体系重复性代码
在性能监视, 事务管理, 安全检查, 缓存中使用
Spring AOP是使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码

面向切面编程,是oop(面向对象编程)的补充和完善,oop是纵向的继承结构来代表公共行为的集合,当需要引入另外一个与业务无关的松散的行为的话就很无力,比如日志系统,所有的对象系统都需要日志,以往的做法会产生大量的重复代码,耦合度提高,重用性降低,显然是不合适的。
aop用横向的代理机制将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低 模块间的耦合度,并有利于未来的可操作性和可维护性

1.1 AOP的术语

木木的Java知识整理——Spring AOP_第1张图片
木木的Java知识整理——Spring AOP_第2张图片
木木的Java知识整理——Spring AOP_第3张图片

二、AOP的底层实现

2.1 JDK的动态代理

适用于使用接口的业务类。

public interface UserDao {
    public void save();

    public void update();

    public void delete();

    public void find();
}
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("保存用户...");
    }

    public void update() {
        System.out.println("修改用户...");
    }

    public void delete() {
        System.out.println("删除用户...");
    }

    public void find() {
        System.out.println("查询用户...");
    }
}

保存、修改、删除、查询方法都是连接点,而save方法是切入点,对其进行权限校验。

public class MyJdkProxy implements InvocationHandler{
    private UserDao userDao;

    public MyJdkProxy(UserDao userDao){
        this.userDao = userDao;
    }

    public Object createProxy(){
        Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),this);
        return proxy;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("save".equals(method.getName())){
            System.out.println("权限校验...");
            return method.invoke(userDao,args);
        }
        return method.invoke(userDao,args);
    }
}

若检测到方法名为save,则进行权限校验。
测试类:

public class SpringDemo1 {
    @Test
    public void demo1(){
        UserDao userDao = new UserDaoImpl();

        UserDao proxy = (UserDao)new MyJdkProxy(userDao).createProxy();
        proxy.save();
        proxy.update();
        proxy.delete();
        proxy.find();
    }
}

输出结果:
木木的Java知识整理——Spring AOP_第4张图片

2.2 CGLIB的动态代理

  • 对于不使用接口的业务类,无法使用JDK动态代理
  • CGlib采用非常底层字节码技术,可以为一个类动态的增加一些方法也可以生成一个类去继承这个类,解决无接口代理问题
public class ProductDao {
    public void save(){
        System.out.println("保存商品...");
    }

    public void update(){
        System.out.println("修改商品...");
    }

    public void delete(){
        System.out.println("删除商品...");
    }

    public void find(){
        System.out.println("查询商品...");
    }
}
public class MyCglibProxy implements MethodInterceptor{

    private ProductDao productDao;

    public MyCglibProxy(ProductDao productDao){
        this.productDao = productDao;
    }

    public Object createProxy(){
        // 1.创建核心类
        Enhancer enhancer = new Enhancer();
        // 2.设置父类
        enhancer.setSuperclass(productDao.getClass());
        // 3.设置回调
        enhancer.setCallback(this);
        // 4.生成代理
        Object proxy = enhancer.create();
        return proxy;
    }

    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if("save".equals(method.getName())){
            System.out.println("权限校验===================");
            return methodProxy.invokeSuper(proxy,args);
        }
        return methodProxy.invokeSuper(proxy,args);
    }
}

public class SpringDemo2 {
    @Test
    public void demo1(){
        ProductDao productDao = new ProductDao();

        ProductDao proxy = (ProductDao) new MyCglibProxy(productDao).createProxy();
        proxy.save();
        proxy.update();
        proxy.delete();
        proxy.find();
    }
}

2.3 代理知识的总结

木木的Java知识整理——Spring AOP_第5张图片
以上两种方法不需要记忆,大多数使用AspectJ来开发AOP。

你可能感兴趣的:(Java知识整理)