Spring AOP快速入门

Posted zZach

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring AOP快速入门相关的知识,希望对你有一定的参考价值。

  • 说明

  1. 目标:学会Spring AOP的基本用法
  2. 适合人群:已经学会Spring IOC基础用法
  3. 源码及jar包已经上传至我的资源,可自行下载

  • 为什么要使用AOP

首先我们来设想一个场景,现在需要做一个能进行整数之间加减乘除的计算器,可以得到如下的代码:


com.spring.aop.Calculator
public interface Calculator 
    public int add(int i, int j);
    public int sub(int i, int j);
    public int mul(int i, int j);
    public int div(int i, int j);

com.spring.aop.CalculatorImpl

public class CalculatorImpl implements Calculator 
    @Override
    public int add(int i, int j) 
        return i + j;
    
    @Override
    public int sub(int i, int j) 
        return i - j;
    
    @Override
    public int mul(int i, int j) 
        return i * j;
    
    @Override
    public int div(int i, int j) 
        return i / j;
    

测试一下:

public class Test 
    public static void main(String[] args) 
        Calculator cal = new CalculatorImpl();
        int result = cal.add(1, 3);
        System.out.println(result);
        

输出结果:4



看上去很棒,似乎一点问题都没有,但是现在需求来了:

在计算之前和计算之后记录参数和结果

那要怎么办呢?变动实现类吧:

//添加日志版
public class CalculatorImpl implements Calculator 
    @Override
    public int add(int i, int j) 
        System.out.println("param: [" + i + "," + j + "]");
        int result = i + j;
        System.out.println("result: " + result);
        return result;
    
    @Override
    public int sub(int i, int j) 
        System.out.println("param: [" + i + "," + j + "]");
        int result = i - j;
        System.out.println("result: " + result);
        return result;
    
    @Override
    public int mul(int i, int j) 
        System.out.println("param: [" + i + "," + j + "]");
        int result = i * j;
        System.out.println("result: " + result);
        return result;
    
    @Override
    public int div(int i, int j) 
        System.out.println("param: [" + i + "," + j + "]");
        int result = i / j;
        System.out.println("result: " + result);
        return result;
    

是不是顿时感觉原本简介的代码变得臃肿而冗余?如果你觉得可以容忍的话,那么试试满足新的需求:

将日志信息记录到数据库中

怎么办,接着每个地方都改一下吗?如果以后要记录到文本文档呢,做成报表呢?甚至是要时不时的在不同的记录方式之间切换呢?
显然,靠手工修改是很麻烦的,那么考虑如何简化一下吧,比如把相同的部分抽取出来,每次计算时先执行记录日志的方法,再计算。这是很有效的,并且Spring已经帮你做到了这些,下面说说如何使用它。

  • 使用Spring AOP

首先,我们应该明确几点:

  1. 既然使用了Spring,那么一切都要交给Spring来管理
  2. 哪些类的哪些方法需要记录日志
  3. 记录日志的方法是什么
  4. 在什么时候记录日志,计算前,计算后,还是出异常后…

明确了这几点之后,就开始理解下面这些代码了:

1.Calculator和CalculatorImpl(未记录日志版)是不用变动的
2.添加Spring IOC和AOP所需要的jar包

核心包
commons-logging-1.1.1.jar
spring-core-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar

AOP
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.net.sf.cglib-2.2.0.jar

3.记录日志的方法
com.spring.aop.AspectLogging

@Component
@Aspect
public class AspectLogging 
    // Before表示在指定方法前执行,execution(method)指定对哪些方法有效
    @Before("execution(public int com.spring.aop.CalculatorImpl.add(int, int))")
    public void BeforeMethod() 
        System.out.println("Method begin");
    
    // @After在指定方法之后执行、使用*将匹配com.spring.aop包下所有的类的所有方法
    @After("execution(* com.spring.aop.*.*(..))")
    public void AfterMethod(JoinPoint joinPoint) 
        // 输出相关信息
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " end");
    

4.Spring配置文件beans.xml:

<?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:p="http://www.springframework.org/schema/p"
    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-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
    <bean id="calculator" class="com.spring.aop.CalculatorImpl" />
    <!-- 需要扫描注解的包 -->
    <context:component-scan base-package="com.spring.aop" />
    <!-- 使Aspect生效 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

测试一下:

public class Test 
    public static void main(String[] args) 
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        Calculator calculator = (Calculator) ctx.getBean("calculator");
        int result = calculator.add(11, 12);
        System.out.println("result:" + result);
        result = calculator.div(21, 3);
        System.out.println("result:" + result);
    

输出结果:

Method begin
The method add end
result:23
The method div end
result:7

可以看到,AOP已经正常工作了,以后需要改动记录日志的方法时只要在AspectLogging类中改动就行。

以上是关于Spring AOP快速入门的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)

SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)

SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)

Spring AOP快速入门

Spring-AOP

Spring学习——快速入门