Spring框架-4(AOP)

Spring系列文章

Spring框架-1(基础)
Spring框架-2(IOC上)
Spring框架-3(IOC下)
Spring框架-4(AOP)
Spring框架-5(JDBC模板&Spring事务管理)
Spring框架-6(SpringMvc)
Spring框架-7(搭建SSM)
Spring框架-8(SpringMVC2)

前面提到AOP可以在不修改源代码的前提下,对程序进行增强,AOP的底层实现其实是JDK的动态代理和CGLIB。那么这篇博客将入门AOP使用配置文件的用法和注解的用法。

我们这篇文章要学什么先看下思维导图吧:

AOP.png

动手之前先了解一些术语

  1. Joinpoint(连接点) -- 所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
  2. Pointcut(切入点) -- 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
  3. Advice(通知/增强) -- 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
  4. Introduction(引介) -- 引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field
  5. Target(目标对象) -- 代理的目标对象
  6. Weaving(织入) -- 是指把增强应用到目标对象来创建新的代理对象的过程
  7. Proxy(代理) -- 一个类被AOP织入增强后,就产生一个结果代理类
  8. Aspect(切面) -- 是切入点和通知的结合,以后咱们自己来编写和配置的

配置文件入门程序

1.需求

现在项目的某一个dao层对数据库有save,update,delete功能,现在我需要不改变功能代码的情况下,再这些功能前面输出log。

2.aspectJ的开发包

  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
  • spring-aspects-4.2.4.RELEASE.jar

使用IDEA创建一个Spring项目,IDEA 会下载导入除了红框框以外的所有jar包。当然红框框哪个包也是需要的。既然IDEA不hi自动导入那么我们可以自己去下载导入。

AOP的Jar包.png

3.创建包结构,编写具体的接口和实现类,切面类

  • com.zhong.aopdemo

    CustomerDao -- 接口

    CustomerDaoImpl -- 实现类

    MyAspectXml -- 切面类

public interface CustomDao {
    void save();

    void update();

    void delete();
}
public class CustomDaoImpl implements CustomDao {
    @Override
    public void save() {
        System.out.println("保存信息");
    }

    @Override
    public void update() {
        System.out.println("更新信息");
    }

    @Override
    public void delete() {
        System.out.println("删除信息");
    }
}
public class MyAspectXml {
    // 定义通知
    public void log() {
        System.out.println("记录日志...");
    }
}

4.配置文件

<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">
    <bean id="customDao" class="com.zhong.aopdemo.CustomDaoImpl"/>
    <bean id="myAspectXml" class="com.zhong.aopdemo.MyAspectXml"/>
    <aop:config>
        <!-- 引入切面类 -->
        <aop:aspect ref="myAspectXml">
            <!-- 定义通知类型:切面类的方法和切入点的表达式 -->
            <aop:before method="log" pointcut="execution(public * com.zhong.aopdemo.CustomDaoImpl.save(..))"/>
            <aop:before method="log" pointcut="execution(public * com.zhong.aopdemo.CustomDaoImpl.update(..))"/>
            <aop:before method="log" pointcut="execution(public * com.zhong.aopdemo.CustomDaoImpl.delete(..))"/>
        </aop:aspect>

    </aop:config>
</beans>

5.运行测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config.xml")
public class Demo {
    @Resource(name="customDao")
    private CustomDao customDao;

    @Test
    public void test() {
        customDao.save();
        customDao.update();
        customDao.delete();
    }
}
运行结果

记录日志...

保存信息

记录日志...

更新信息

记录日志...

删除信息

看到结果,没问题那么我们的入门程序成功写完了。我们现在成功在save,update,delete这三个方法前记录了日志

分析一些术语

切入点的表达式

再配置切入点的时候,需要定义表达式,重点的格式如下:execution(public * *(..)),具体展开如下:

  1. 切入点表达式的格式如下:

    • execution([修饰符] 返回值类型 包名.类名.方法名(参数))
  2. 修饰符可以省略不写,不是必须要出现的。

  3. 返回值类型是不能省略不写的,根据你的方法来编写返回值。可以使用 * 代替。

  4. 包名例如:com.itheima.demo3.BookDaoImpl

    • 首先com是不能省略不写的,但是可以使用 * 代替
    • 中间的包名可以使用 * 号代替
    • 如果想省略中间的包名可以使用 ..
  5. 类名也可以使用号代替,也有类似的写法:DaoImpl

  6. 方法也可以使用 * 号代替

  7. 参数如果是一个参数可以使用*号代替,如果想代表任意参数使用 ..

AOP的通知类型

  1. 前置通知
  • 在目标类的方法执行之前执行。
  • 配置文件信息:<aop:after method="before" pointcut-ref="myPointcut3"/>
  • 应用:可以对方法的参数来做校验
  1. 最终通知
  • 在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。
  • 在配置文件中编写具体的配置:<aop:after method="after" pointcut-ref="myPointcut3"/>
  • 应用:例如像释放资源
  1. 后置通知
  • 方法正常执行后的通知。
  • 在配置文件中编写具体的配置:<aop:after-returning method="afterReturning" pointcut-ref="myPointcut2"/>
  • 应用:可以修改方法的返回值
  1. 异常抛出通知
  • 在抛出异常后通知
  • 在配置文件中编写具体的配置:<aop:after-throwing method="afterThorwing" pointcut-ref="myPointcut3"/>
  • 应用:包装异常的信息
  1. 环绕通知
  • 方法的执行前后执行。
  • 在配置文件中编写具体的配置:<aop:around method="around" pointcut-ref="myPointcut2"/>
  • 要注意:目标的方法默认不执行,需要使用ProceedingJoinPoint对来让目标对象的方法执行。

注解方式实现

1.注解定义切面类

  1. 添加切面和通知的注解
  • @Aspect -- 定义切面类的注解
  1. 通知类型(注解的参数是切入点的表达式)
    • @Before -- 前置通知
    • @AfterReturing -- 后置通知
    • @Around -- 环绕通知
    • @After -- 最终通知
    • @AfterThrowing -- 异常抛出通知
@Component
@Aspect
public class MyAspectXml {
    // 定义通知
    @Before("execution(public * com.zhong.aopdemo.CustomDaoImpl.save(..))")
    public void log() {
        System.out.println("记录日志...");
    }
}

2.修改配置文件,给使用的类加上Component注解

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.zhong.aopdemo"/>
    <!--在配置文件中开启自动代理-->
    <aop:aspectj-autoproxy/>
</beans>

测试结果

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config.xml")
public class Demo {
    @Resource(name="customDao")
    private CustomDao customDao;

    @Test
    public void test() {
        customDao.save();
    }
}

结果

记录日志...

保存信息

这就成功了。其实写到这里都是一些基础的东西。从配置文件到注解方式,可见注解是多么的强大。多么的方便,如果各位不太懂注解,建议先去熟悉熟悉注解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 ...
    谢随安阅读 3,122评论 0 9
  • 没有梦,你怎么知道你自己到底想要什么,又要去到哪里? 上大学,初到车水马龙的大城市,有对新生活的憧憬,也有对这座城...
    simple_木柯阅读 285评论 2 4
  • 猴年要来,我人生的第二次本命年。我决定 暂时不玩英雄联盟了。这不是一时冲动,之前我也试过多次,没有成功过。迷茫时我...
    常磐阅读 199评论 0 0
  • 光|夕侧
    林默丶阅读 234评论 0 0