摘要: 本文结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码。若有描述错误之处,欢迎指正。

我们知道,使用面向对象编程(OOP)有一些弊端,当需要为多个不具有继承关系的对象引人同一个公共行为时,例如日志、安全检测等,我们只有在每个对象里引用公共行为,这样程序中就产生了大量的重复代码,程序就不便于维护了,所以就有了一个对面向对象编程的补充,即面向方面编程(AOP),AOP所关注的方向是横向的,不同于OOP的纵向。

Spring中提供了AOP的实现,但是在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并进行一些较为复杂的配置。低版本Spring AOP的配置是被批评最多的地方。Spring听取了这方面的批评声音,并下决心彻底改变这一现状。在Spring2.0中,SpringAOP已经焕然一新,你可以使用@AspectJ注解非常容易地定义一个切面,不需要实现任何的接口。

Spring 2.0采用@AspectJ注解对POJO进行标注,从而定义一个包含切点信息和增强横切逻辑的切面。Spring 2.0可以将这个切面织人到匹配的目标Bean中。@AspectJ注解使用AspectJ切点表达式语法进行切点定义,可以通过切点函数、运算符、通配符等高级功能进行切点定义,拥有强大的连接点描述能力。我们先来直观地浏览一下Spring中的AOP实现。

接下来一起看看@AspectJ注解是如何使用的。

目录

一、创建用于拦截的bean

二、创建Advisor

三、创建配置文件

四、测试

在开始前,先配置Aspect。

<!-- aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>

一、创建用于拦截的bean

在实际工作中,此bean可能是满足业务需要的核心逻辑,例如test方法中可能会封装着某个核心业务,但是,如果我们想在test前后加人口志来跟踪调试,如果直接修改源码并不符合面向对象的设计方法,而且随意改动原有代码也会造成一定的风险,还好接下来的Spring帮我们做到了这一点。

public class Audience {

    private String name = "audience";

    public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public void watch() {
System.out.println("Watch movie");
}
}

二、创建Advisor

Spring中摒弃了最原始的繁杂配置方式而采用@AspectJ注解对POJO进行标注,使AOP 的的工作大大简化,例如,在AspectJAudience类中,我们要做的就是在所有类的watch方法执行前在控制台中打印silenceCellPhone和takeSeat,而在所有类的watch方法执行后打印applause,同时又使用环绕的方式在所有类的watch方法执行前后再次分别打印Silencing cell phone和CLAP CLAP CLAP。

@Aspect
public class AspectJAudience {
/**
* 定义一个公共的切点
*/
@Pointcut("execution(* *.watch(..))")
public void watch() { } /**
* 目标方法执行之前调用
*/
@Before("watch()")
public void silenceCellPhone() {
System.out.println("Silencing cell phone");
} /**
* 目标方法执行之前调用
*/
@Before("watch()")
public void takeSeat() {
System.out.println("Taking seat");
} /**
* 目标方法执行完后调用
*/
@AfterReturning("watch()")
public void applause() {
System.out.println("CLAP CLAP CLAP");
} /**
* 目标方法发生异常时调用
*/
@AfterThrowing("watch()")
public void demandRefund() {
System.out.println("Demanding a refund");
} /**
* 环绕通知
* @param p 通过它调用目标方法
*/
@Around("watch()")
public Object aroundWatch(ProceedingJoinPoint p) {
Object o = null;
try {
System.out.println("Silencing cell phone");
o = p.proceed();
System.out.println("CLAP CLAP CLAP!!!");
} catch (Throwable e) {
System.out.println("Demanding a refund");
}
return o;
}
}

三、创建配置文件

XML是Spring的基础。尽管Spring—再简化配置,并且大有使用注解取代XML配置之势,但是无论如何,至少现在XML还是Spring的基础。要在Spring中开启AOP功能,还需要在配罝文件中作如下声明:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <aop:aspectj-autoproxy/> <bean id="audience" class="org.cellphone.uc.aop.Audience"/>
<bean id="aspectJAudience" class="org.cellphone.uc.aop.AspectJAudience"/>
</beans>

四、测试

经过以上步骤后,便可以验证Spring的AOP为我们提供的神奇效果了。

public class AspectJMain {

    public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/aop-test.xml");
Audience audience = (Audience) context.getBean("audience");
audience.watch();
}
}

不出意外,我们会看到控制台中打印了如下代码:

Silencing cell phone
Silencing cell phone
Taking seat
Watch movie
CLAP CLAP CLAP!!!
CLAP CLAP CLAP

Spring实现了对所有类的watch方法进行增强,使辅助功能可以独立于核心业务之外,方便 与程序的扩展和解耦。

那么,Spring究竞是如何实现AOP的呢?首先我们知道,Spring是否支持注解的AOP是由一个配置文件控制的,也就是<aop:aspectj-autoproxy/>,当在配置文件中声明了这句配置的时候,Spring就会支持注解的AOP,那么我们的分析就从这句注解开始。

Spring AOP源码分析(一)使用示例的更多相关文章

  1. spring AOP源码分析(三)

    在上一篇文章 spring AOP源码分析(二)中,我们已经知道如何生成一个代理对象了,那么当代理对象调用代理方法时,增强行为也就是拦截器是如何发挥作用的呢?接下来我们将介绍JDK动态代理和cglib ...

  2. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  3. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  4. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  5. Spring AOP 源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

  6. Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

    AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...

  7. 5.2 Spring5源码--Spring AOP源码分析二

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  8. 5.2 spring5源码--spring AOP源码分析二--切面的配置方式

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  9. spring aop 源码分析(三) @Scope注解创建代理对象

    一.源码环境的搭建: @Component @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedP ...

  10. 最简 Spring AOP 源码分析!

    前言 最近在研究 Spring 源码,Spring 最核心的功能就是 IOC 容器和 AOP.本文定位是以最简的方式,分析 Spring AOP 源码. 基本概念 上面的思维导图能够概括了 Sprin ...

随机推荐

  1. Git——远程操作详解

    转载自:http://www.ruanyifeng.com/blog/2014/06/git_remote.html 作者: 阮一峰 日期: 2014年6月12日 Git是目前最流行的版本管理系统,学 ...

  2. ArcEngine9.3迁移至ArcObject10.1

    以前写的程序,现在看起来真是相当的青涩,当时写的东西是显得多么地无知啊,很多应该写成一个类,有些需要优化,需要多线程,代码需要加密--总一种想修改的冲动.但这也需要时间和精力.下面准备将原来的程序进行 ...

  3. 打包jar问题

    一. 先说一下一般是动态布局最好,效率高,动态就是java写布局,这是 老外的专长,一般res目录是不能打包的,布局动态写,其余的就是图片什么的了,可以建一个assess文件夹,把图片放里面,打jar ...

  4. CSS3 选择器用法小结

    表单选择器: /*:enabled 可用的 :disabled 被禁用的 :focus 获取了焦点的 多用在表单元素上*/ input:enabled {...} input:disabled {.. ...

  5. Pig类型转换

    users.data的内容如下: lisg 28 75 dengsl 24 88 强制类型转换 users = load '/users.data' fehed = foreach users gen ...

  6. 解决initializing java tooling(1%)

    这是wtp的一个bug,下载附件runtimePatch_327801.zip,解压,放到eclipse下,重启就好了.

  7. CentOS6.4 下安装 jdk1.7.0_67

    1.卸载系统自带的jdk 1.1.查看该操作系统上是否已经安装了jdk [root@xhTest-1 ~]# rpm -qa | grep jdk 1.2.删除系统自带的jdk [root@xhTes ...

  8. [翻译] ios-image-filters

    ios-image-filters https://github.com/esilverberg/ios-image-filters photoshop-style filter interface ...

  9. 使用UICollectionView

    使用UICollectionView 使用UICollectionView的流程: 1. 设定一个UICollectionViewFlowLayout 2. 使用这个设定的UICollectionVi ...

  10. 测试SDWebImage淡入淡出效果在UITableView中的重用显示问题

    测试SDWebImage淡入淡出效果在UITableView中的重用显示问题 这个是在上一篇教程的基础上所添加的测试环节! 效果图(从效果图中看是没有任何重用问题的): 源码: ImageCell.h ...