欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring AOP的理解

程序员文章站 2022-07-12 14:29:20
...

周一不知道干啥,更新一点复习知识点。理论有部分摘抄简化。

AOP面向切面编程,可以说是对OOP的补充和完善,在原OOP面向对象编程中,引用封装继承和多态等概念来建立一种对象的层次结构。也就是说 OOP允许你定义从上到下的关系,但不适合从左到右的关系,例如日志,事务,权限认证,会导致代码大量重复,不利于各个模块的重用。AOP则称之为“横切” ,刨开封装的内部对象,将软件分为 核心关注 点和 横切关注点。业务的主要流程就是核心关注点,而与之关系不大的就是横切关注点。横切关注点的特点就是:他们经常发生在核心关注点的多出,而且各个都基本相似。比如刚才提到的日志,事务,权限认证。将应用程序中的商业逻辑同对其提供支持的通用服务进行分离

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
具体可以在下面的场景中使用:

  1. Authentication 权限
  2. Caching 缓存
  3. Context passing 内容传递
  4. Error handling错误处理
  5. Lazy loading 懒加载
  6. Debugging  调试
  7. logging, tracing, profiling andmonitoring 记录跟踪 优化 校准
  8. Performance optimization 性能优化
  9. Persistence  持久化
  10. Resource pooling 资源池
  11. Synchronization 同步
  12. Transactions 事务

expression切面规则表达式:
Spring AOP的理解
5个切入点:

前置 aop:before 在原业务发生之前触发 业务出现异常不影响 @Before
后置 aop:after 在原业务发生之后触发 业务出现异常不影响 @After
返回 aop:after-returning 在原业务不抛出异常时触发 获取原业务返回值 甚至可以修改结果 @AfterReturning
异常 aop:after-throwing 在原业务抛出异常时触发 如果业务层内部处理异常 对外而言 意味着该业务正常执行 @AfterThrowing
*环绕 aop:around 控制原业务回调 最符合代理模式编程模式 其原理是动态代理
其关键是 org.aspectj.lang.ProceedingJoinPoint @Around

配置式例子:
被切入点:

public class MathCaculator {
    /**
     * 希望在业务h执行之前 之后 错误  打印相关信息
     * @param i
     * @param j
     * @return
     */
    public int dev(int i, int j) {
        return i / j;
    }
}

java配置:LogAspects 切面类

@Aspect

public class LogAspects {

    @Pointcut("execution(public int com.thl.aop.apotest.MathCaculator.dev(int,int ))")

    public void pointCut() {
    }

    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint) {
        System.out.println("运行前:" + joinPoint.getSignature().getName() + "  " + Arrays.asList(joinPoint.getArgs()));
    }

    @After("pointCut()")
    public void logEnd() {
        System.out.println("运行结束:结果");
    }

    @AfterReturning(value = "pointCut()", returning = "obj")
    public void logRun(JoinPoint joinPoint,Object obj) {
        System.out.println("运行时:" +joinPoint+ obj );
    }

    @AfterThrowing(value = "pointCut()", throwing = "e")
    public void logException(Exception e) {
        System.out.println("运行异常:"+e);
    }
}

添加bean: MainConfigAOP

@EnableAspectJAutoProxy
@Configuration
public class MainConfigAOP {

    @Bean
    public MathCaculator caculator() {
        return new MathCaculator();
    }

    @Bean
    public LogAspects logAspects() {
        return new LogAspects();
    }
}

test:

  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext((MainConfigAOP.class));
    MathCaculator mathCaculator = (MathCaculator) context.getBean("caculator");
    int dev = mathCaculator.dev(1, 1);
    System.out.println(dev);

原理:
围绕:@EnableAspectJAutoProxy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   boolean proxyTargetClass() default false;
   boolean exposeProxy() default false;

}

获取当前bean的所有增强器(通知方法)
获取当前的bean所有的增强器,找到那些方法时需要切入bean的方法。
获取到能在bean使用的增强器。
给增强器排序
保存当前的bean在advisedBeans中;
如果当前的bean需要增强,创建当前bean的代理对象;
获取到所有增强器(通知方法)
保存在proxyFactory中
创建代理对象:自动举例,是jdk动态代理(实现接口),还是cglib代理(可以强制)
JdkDynamicAopProxy(config)
objenesisCglibAopProxy(config)
如果是cglib,给容器返回当前组件的使用的cglib增强代理对象,执行目标方法时,代理对象就会执行通知方法的流程。
链式获取每一个拦截器,执行invoke方法,每个拦截器等待下一个拦截器执行返回。保证通知方法与目标方法的执行顺序
Spring AOP的理解

相关标签: spring aop