7.1-spring 动态 AOP

本文详细介绍了Spring的AOP(面向切面编程)概念,包括核心组件、使用场景、术语解释及实际示例。通过示例展示了如何配置AOP,定义切点、通知,以及在测试中观察AOP的运行效果,帮助读者深入理解并应用Spring AOP。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring 动态 AOP

AOP(Aspect Oriented Programming) 即面向切面编程 ,不同于
OOP(Object Oriented Programming) 面向对象编程,AOP关注的方向是横向的,而OOP关注的方向是纵向的,spring AOP是spring关键组件之一,它是AOP概念的具体实现方案,是对spring IOC 的补充,但是spring IOC不依赖spring AOP。

spring AOP 使用场景

  • Authentication 权限
  • Caching 缓存
  • Context passing 内容传递
  • Error handling 错误处理
  • Lazy loading 懒加载
  • Debugging 调试
  • logging, tracing, profiling and monitoring 记录跟踪 优化 校准
  • Performance optimization 性能优化
  • Persistence  持久化
  • Resource pooling 资源池
  • Synchronization 同步
  • Transactions 事务

AOP 术语

  • Join point(连接点):具体拦截的对象,一般是指具体的某个方法
  • Pointcut (切点):可以理解成连接点的集合,比方A类的test方法和B类的test方法,一般通过正则规则匹配
  • Advice(通知):指aop对连接点采取的动作类型,分为前置通知(before advice)、后置通知(after advice)、环绕通知(around advice)、事后返回通知(afterReturning advice)和异常通知(afterThrowing advice)
  • Target object(目标对象):即被代理的对象
  • Introduction(引入):是指新引入的类和其方法,增强现有bean的功能
  • Weaving (织入):是指通过动态代理技术,为原有对象生成代理对象,然后拦截定义的切点,并且执行各类通知的过程
  • Aspect (切面):是一个可以定义切点、各类通知和引入的内容,即对以上内容的具体实现

spring AOP 使用示例

① 引入spring-aop 和 spring-aspects依赖

 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-aop</artifactId>
     <version>5.0.0.RELEASE</version>
 </dependency>

 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-aspects</artifactId>
     <version>5.0.0.RELEASE</version>
 </dependency>

② 定义需要拦截的bean

package com.springtest.model;

public class AopTestBean {

    public void printStr(String str) {
        if (str == null) {
            throw new RuntimeException("str 为空!");
        }
        System.out.println("com.springtest.model.AopTestBean 输出: " + str);
    }
}

③ 定义切面(其中包括切点,通知等)

package com.springtest.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
public class AspectJTest {

    //切点
    @Pointcut("execution(* *.printStr(..))")
    public void printStr() {
    }

    //前置通知
    @Before("printStr()")
    public void beforePrintStr() {
        System.out.println("beforePrintStr");
    }

    //后置通知
    @After("printStr()")
    public void afterPrintStr() {
        System.out.println("afterPrintStr");
    }

    //环绕通知
    @Around("printStr()")
    public Object aroundPrintStr(ProceedingJoinPoint p) throws Throwable {
        System.out.println("aroundPrintStr start");
        Object o = p.proceed();
        System.out.println("aroundPrintStr end");
        return o;
    }

    //返回通知
    @AfterReturning("printStr()")
    public void afterReturningPrintStr() {
        System.out.println("afterReturningPrintStr");
    }

    //异常通知
    @AfterThrowing("printStr()")
    public void afterThrowingPrintStr() {
        System.out.println("afterThrowingPrintStr");
    }
}

④ 在配置文件中启用aop,以及在容器中初始化测试bean和切面
aop-test.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <aop:aspectj-autoproxy/>

    <bean id="aopTestBean" class="com.springtest.model.AopTestBean"></bean>
    <bean class="com.springtest.aop.AspectJTest"></bean>
</beans>

⑤ 编写测试类

import com.springtest.model.AopTestBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringXmlContextTest {

    @Test
    public void aopTest() {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("aop-test.xml");
        AopTestBean aopTestBean = (AopTestBean) classPathXmlApplicationContext.getBean("aopTestBean");
        aopTestBean.printStr("天气晴朗");
        System.out.println("----------------------------------------------");
        aopTestBean.printStr(null);
    }

}

测试结果如下:

"C:\Program Files\Java\jdk1.8.0_121\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:6431,suspend=y,server=n -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:C:\Users\Administrator\.IntelliJIdea2019.1\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2019.1\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2019.1\plugins\junit\lib\junit-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2019.1\plugins\junit\lib\junit5-rt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\rt.jar;D:\workspace\spring-test-ws\beaninit\target\test-classes;D:\workspace\spring-test-ws\beaninit\target\classes;D:\m2\repository\org\springframework\spring-core\5.0.0.RELEASE\spring-core-5.0.0.RELEASE.jar;D:\m2\repository\org\springframework\spring-jcl\5.0.0.RELEASE\spring-jcl-5.0.0.RELEASE.jar;D:\m2\repository\org\springframework\spring-context\5.0.0.RELEASE\spring-context-5.0.0.RELEASE.jar;D:\m2\repository\org\springframework\spring-beans\5.0.0.RELEASE\spring-beans-5.0.0.RELEASE.jar;D:\m2\repository\org\springframework\spring-expression\5.0.0.RELEASE\spring-expression-5.0.0.RELEASE.jar;D:\m2\repository\org\springframework\spring-aop\5.0.0.RELEASE\spring-aop-5.0.0.RELEASE.jar;D:\m2\repository\org\springframework\spring-aspects\5.0.0.RELEASE\spring-aspects-5.0.0.RELEASE.jar;D:\m2\repository\org\aspectj\aspectjweaver\1.8.11\aspectjweaver-1.8.11.jar;D:\m2\repository\junit\junit\4.12\junit-4.12.jar;D:\m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 SpringXmlContextTest,aopTest
Connected to the target VM, address: '127.0.0.1:6431', transport: 'socket'
五月 05, 2021 5:12:11 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6dde5c8c: startup date [Wed May 05 17:12:11 CST 2021]; root of context hierarchy
五月 05, 2021 5:12:11 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [aop-test.xml]
aroundPrintStr start
beforePrintStr
com.springtest.model.AopTestBean 输出: 天气晴朗
aroundPrintStr end
afterPrintStr
afterReturningPrintStr
----------------------------------------------
aroundPrintStr start
beforePrintStr
afterPrintStr
afterThrowingPrintStr

java.lang.RuntimeException: str 为空!

	at com.springtest.model.AopTestBean.printStr(AopTestBean.java:7)
	at com.springtest.model.AopTestBean$$FastClassBySpringCGLIB$$13686d5d.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
	at com.springtest.aop.AspectJTest.aroundPrintStr(AspectJTest.java:26)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:643)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:632)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
	at com.springtest.model.AopTestBean$$EnhancerBySpringCGLIB$$6b2897da.printStr(<generated>)
	at SpringXmlContextTest.aopTest(SpringXmlContextTest.java:29)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)


Disconnected from the target VM, address: '127.0.0.1:6431', transport: 'socket'

Process finished with exit code -1

官方文档:
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值