Spring的AOP

1.什么是AOP?

AOP Aspect Oriented Programing面向切面编程

AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)

比如说:在UserDao中有保存、修改、删除等操作的时候,需要对该操作有一个权限的验证,传统的方法就是在保存的方法里面先编写权限校验的代码,如果使用传统的方法,那么在每一个操作前都需要用这个方法去校验,导致代码的冗余;所以现在出现了AOP来解决此问题

传统的方式如下:
在这里插入图片描述

没有AOP思想的时候,用传统的纵向继承:

在这里插入图片描述

横向抽取其实就是代理机制(Proxy)

在这里插入图片描述
Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码

2.AOP的相关术语

Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点

Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.

Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)

Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field.

Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
Aspect(切面):是切入点和通知(引介)的结合

理解连接点、切入点的意思;拦截后需要做的事情叫做增强(Advice)
比如:在保存前做个身份校验(前置通知)
在删除的时候,做个日志记录(后置通知)
Target目标对象:例如UserDaoImpl实现类就是目标对象

Weaving(织入):将Advice应用到Target的过程

Proxy(切面):就是切入点和通知idea组合
在这里插入图片描述

3.代理知识的总结

Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术为目标Bean执行横向织入
程序中应优先对接口创建代理,便于程序解耦维护

标记为final的方法,不能被代理,因为无法进行覆盖
JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰- CGLib 是针对目标类生产子类,因此类或方法不能使final的

Spring只支持方法的连接点,不支持属性连接点

4.JDK的动态代理
在这里插入图片描述

4.代理的简单例子

4.1接口类


public interface UserDao {
    public void save();

    public void update();

    public void delete();

    public void find();
}

4.2接口实现类

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("查询用户...");
    }
}

4.3测试类

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();
    }
}

4.4代理类

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);
    }
}

InvocationHandler

5.使用CGLIB生成代理

在这里插入图片描述
5.1接口类

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("查询商品...");
    }
}

5.2 测试类

```java
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();
    }
}

5.3代理类


 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);
    }
}

6.Spring的增强类型

7.Spring AOP的切面类型

Advisor:代表一般切面,Advice本身就是一个切面,对目标类所有方法进行拦截

PointcutAdvisor:代表具有切点的切面,可以指定拦截目标类哪些方法

IntroductionAdvisor :代表引介切面,针对引介通知而使用切面(不要求掌握)

8.Spring自动创建AOP代理模式

前面的案例中,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护量巨大·解决方案∶自动创建代理

  • BeanNameAutoProxyCreator根据Bean名称创建代理
  • DefaultAdvisorAutoProxyCreator根据Advisor本身包含信息创建代理-
  • AnnotationAwareAspectJAutoProxyCreator基于Bean中的AspectJ注解进行自动代理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值