Spring系列之AOP分析(二)

简介:

终于要正式开始SpringAOP的分析工作了,在这之前先问个问题:关于AOP你认为最重要的是哪几个地方?我觉得有这样几个地方(理解的不对的地方欢迎指出):一个是AOP的配置(拦截规则的配置),一个是代理对象的创建,一个是统一的拦截调用过程。关于AOP的配置Spring是自己定义了一套规则同时集成了AspectJ的语法,抽象为了Pointcut类。代理对象的创建,SpringAOP定义了一个工厂类AopProxy,同时支持JDK动态代理和CGlib动态代理。统一的拦截调用过程则是使用了AOP联盟中定义的拦截过程:Advice----->Interceptor------->MethodInterceptor。但是SpringAOP在这个基础上做了一些扩展,形成了自己的一套体系。接下来先介绍一下长得很像三胞胎的三个类:
Advice:SpringAOP联盟中定义的类。是一个标识性的接口。通知类型的接口。同时也是Interceptor、MethodInterceptor的父类。通知类型都有去实现的一个接口。
Advisor:关联了Advice和Pointcut。在SpringAOP中是一个很关键的类。上起到了连接点的匹配下起到了通知类型的调用。统一了拦截的调用过程。
Advised:关联了Advisor和TargetSource的类。也是AOP中一个很关键的类。AOP进行方法拦截的时候,就是从它里面获取的拦截调用链。
一个大致的关系如下:
Advised_Advisor_Advice
下面我们先写一个使用SpringAOP的小例子,这里使用了AspectJ中的语法。小例子如下:
先定义一个切面类和一个前置通知:

@Aspect
public class AopAdviceConfig {

    @Before("execution(* com.zkn.spring.learn.aop.program.service..*.*(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println(joinPoint.getThis());
        System.out.println("我是前置通知....");
    }
}
//定义一个接口
public interface AspectJService {

    /**
     * 测试前置通知
     */
    void beforeAdvice();

    /**
     * 测试后置通知
     */
    void afterAdvice();
}
//实现类
public class AspectJServiceImpl implements AspectJService {

    @Override
    public void beforeAdvice() {
        System.out.println("测试前置通知,我是第一个Service。。。。。。");
    }

    /**
     * 测试后置通知
     */
    @Override
    public void afterAdvice() {
        System.out.println("测试AspectJ后置通知。。。。");
    }
}

我们用编程的方式去进行一个AOP的拦截功能。

public class AspectJProxyFactoryLearn {

    public static void main(String[] args) {
        //手工创建一个实例
        AspectJService aspectJService = new AspectJServiceImpl();
        //使用AspectJ语法 自动创建代理对象
        AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService);
        //添加切面和通知类
        aspectJProxyFactory.addAspect(AopAdviceConfig.class);
        //创建代理对象
        AspectJService proxyService = aspectJProxyFactory.getProxy();
        //进行方法调用
        proxyService.beforeAdvice();
    }
}

我们看一下输出结果:
AspectJProxyFactory
从上面的输出结果来看,我们的AOP拦截功能是生效了。但是对于这样的操作你可能会很奇怪,感觉SpringAOP还能这样玩?上面的AspectJProxyFactory这个类又是什么鬼?怎么只调用了一下addAspect方法,然后调用getProxy方法生成代理对象,这样就能进行AOP拦截了?我们在下面的文章中慢慢为你解谜。
在进行AspectJProxyFactory分析之前先来看一下AspectJProxyFactory的UML类图:
AspectJProxyFactory
AspectJProxyFactory的类图如上所示,我们可以看到它是Advised的一个子类。先把这个图印在脑子里。我们先来看第一段代码:

AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService);
//对应的AspectJProxyFactory构造函数的内容
public AspectJProxyFactory(Object target) {
    Assert.notNull(target, "Target object must not be null");
    setInterfaces(ClassUtils.getAllInterfaces(target));
    setTarget(target);
}

当我们调用AspectJProxyFactory的有参构造函数时,它做了这几件事,检测目标对象不能为null,设置目标对象的所有的接口,设置目标对象。
获取类上的所有的接口是通过调用ClassUtils.getAllInterfaces来获取的。这个方法可以获取类上的所有接口,包括父类上的接口,但是它不能获取接口的接口。意思是如果:类A继承了类B,类B实现了接口C,接口C继承了接口D,如果传入的参数是类A,这里是可以获取到接口C,但是获取不到接口D的

    //AdvisedSupport中添加接口信息
    public void setInterfaces(Class<?>... interfaces) {
        Assert.notNull(interfaces, "Interfaces must not be null");
        //先清空原来的接口信息 是一个List
        this.interfaces.clear();
        for (Class<?> ifc : interfaces) {
            addInterface(ifc);
        }
    }
    //AdvisedSupport中的方法
    public void addInterface(Class<?> intf) {
        Assert.notNull(intf, "Interface must not be null");
        //如果不是接口 抛出异常
        if (!intf.isInterface()) {
            throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
        }
        if (!this.interfaces.contains(intf)) {
            this.interfaces.add(intf);
            adviceChanged();
        }
    }
    //ProxyCreatorSupport中的方法
    protected void adviceChanged() {
        super.adviceChanged();
        synchronized (this) {
            if (this.active) {
                //给Advised的监听器发送通知 通知Advised的变化 
                //在Spring中没有默认的实现
                for (AdvisedSupportListener listener : this.listeners) {
                    listener.adviceChanged(this);
                }
            }
        }
    }
    //AdvisedSupport中的方法
    protected void adviceChanged() {
        //清空缓存的方法信息 这里可以思考一下为什么当Interface变化的时候,会清空methodCache
        //Map<MethodCacheKey, List<Object>> methodCache
        //为什么这个类名是adviceChanged???
        this.methodCache.clear();
    }

设置目标对象

    public void setTarget(Object target) {
        //注意这里是将目标对象封装为了 SingletonTargetSource 是一个单例的
        //这里一定要记着 SingletonTargetSource中存放的是我们的目标对象 不是代理对象
        //这里调用的是AdvisedSupport中的方法 setTargetSource这个方法是Advised中定义的方法
        setTargetSource(new SingletonTargetSource(target));
    }
    // AdvisedSupport
    public void setTargetSource(TargetSource targetSource) {
        this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
    }

剩下的我们在下一章分析。

相关文章
|
10天前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
34 14
|
29天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
12天前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
38 5
|
16天前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
45 8
|
16天前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
16天前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
32 5
|
16天前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
25 4
|
2月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
43 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
1月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
30 1
|
1月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
35 0