Spring中使用AOP的几种方式

在Spring中使用AOP进行切面编程主要有以下几种方式:

  1. XML配置
  2. XML+注解
  3. 纯注解

XML配置

新建实体类XmlAopBean及切片类XmlAopService

实体类XmlAopBean

package XmlAopBean;

import java.text.MessageFormat;

public class XmlAopBean {

    public void runWithoutArgs() {
        System.out.println("这是无参方法。");
    }

    public void runWithArgs(Integer arg) {
        Integer i=1/arg;
        System.out.println(MessageFormat.format("这是有参方法,参数:{0}", arg));
    }
}


AOP类XmlAopService

package XmlAopBean;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import java.text.MessageFormat;

public class XmlAopService {

    public void doBefore(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("前置通知参数:{0}", joinPoint.getArgs()));
    }

    public void doAfter(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("后置通知方法:{0}", joinPoint.getSignature()));
    }

    public void doEnd(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("最终通知目标类:{0}", joinPoint.getTarget()));
    }

    public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println(MessageFormat.format("前环绕通知代码位置:{0}", proceedingJoinPoint.getSourceLocation()));
        proceedingJoinPoint.proceed();
        System.out.println(MessageFormat.format("后环绕通知执行类型:{0}", proceedingJoinPoint.getKind()));
    }
    
    public void doAfterThrow(JoinPoint joinPoint){
        System.out.println(MessageFormat.format("异常通知{0}", joinPoint.getThis()));
    }
}

JoinPoint :获取切入点方法的相关信息

ProceedingJoinPoint :环绕通知内切入点方法占位

xmlAopBean.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       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-4.0.xsd"
>

    <bean class="XmlAopBean.XmlAopBean" id="xmlAopBean"/>
    <bean class="XmlAopBean.XmlAopService" id="xmlAopService"/>

    <aop:config>
        <aop:pointcut id="xmlAopPointCut" expression="execution(void XmlAopBean.XmlAopBean.*(..))"/>

        <aop:aspect ref="xmlAopService">
            <aop:before method="doBefore" pointcut-ref="xmlAopPointCut"/>
            <aop:after method="doAfter" pointcut-ref="xmlAopPointCut"/>
            <aop:after-returning method="doEnd" pointcut-ref="xmlAopPointCut"/>
            <aop:around method="doAround" pointcut-ref="xmlAopPointCut"/>
        </aop:aspect>
    </aop:config>

</beans>
导入依赖
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.14</version>
        </dependency>
引入约束
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="...
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"
配置AOP
<aop:config>
        <aop:pointcut id="xmlAopPointCut" expression="execution(void XmlAopBean.XmlAopBean.*(..))"/>

        <aop:aspect ref="xmlAopService">
            <aop:before method="doBefore" pointcut-ref="xmlAopPointCut"/>
            <aop:after method="doAfter" pointcut-ref="xmlAopPointCut"/>
            <aop:after-returning method="doEnd" pointcut-ref="xmlAopPointCut"/>
            <aop:around method="doAround" pointcut-ref="xmlAopPointCut"/>
        </aop:aspect>
    </aop:config>

单元测试

import AnnotationAopBean.AnnotationAopBean;
import XmlAopBean.XmlAopBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {BaseConfig.class})
public class AOPBeanTest {

    ...

    @Test
    public void xmlAopBeanTest() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("xmlAopBean.xml");

        XmlAopBean xmlAopBean = applicationContext.getBean("xmlAopBean", XmlAopBean.class);

        xmlAopBean.runWithArgs(1);
        xmlAopBean.runWithoutArgs();
    }
}


输出结果

前置通知参数:1
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@6d5620ce
这是有参方法,参数:1
后环绕通知执行类型:method-execution
最终通知目标类:XmlAopBean.XmlAopBean@60db1c0e
后置通知方法:void XmlAopBean.XmlAopBean.runWithArgs(Integer)
前置通知参数:{0}
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@18f8cd79
这是无参方法。
后环绕通知执行类型:method-execution
最终通知目标类:XmlAopBean.XmlAopBean@60db1c0e
后置通知方法:void XmlAopBean.XmlAopBean.runWithoutArgs()


XML+注解

新建实体类XmlAnnotationAopBean和AOP类XmlAnnotationAopService

实体类XmlAnnotationAopBean

package XmlAnnotationAopBean;

import org.springframework.stereotype.Component;

import java.text.MessageFormat;

@Component
public class XmlAnnotationAopBean {

    public void runWithoutArgs() {
        System.out.println("这是无参方法。");
    }

    public void runWithArgs(Integer arg) {
        Integer i = 1 / arg;
        System.out.println(MessageFormat.format("这是有参方法,参数:{0}", arg));
    }
}

AOP类XmlAnnotationAopService

package XmlAnnotationAopBean;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;

@Component
@Aspect
public class XmlAnnotationAopService {

    @Pointcut("execution(void XmlAnnotationAopBean.*(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("前置通知参数:{0}", joinPoint.getArgs()));
    }

    @After("pointCut()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("后置通知方法:{0}", joinPoint.getSignature()));
    }

    @AfterReturning("pointCut()")
    public void doEnd(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("最终通知目标类:{0}", joinPoint.getTarget()));
    }

    @Around("pointCut()")
    public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println(MessageFormat.format("前环绕通知代码位置:{0}", proceedingJoinPoint.getSourceLocation()));
        proceedingJoinPoint.proceed();
        System.out.println(MessageFormat.format("后环绕通知执行类型:{0}", proceedingJoinPoint.getKind()));
    }
    
    @AfterThrowing("pointCut()")
    public void doAfterThrow(JoinPoint joinPoint){
        System.out.println(MessageFormat.format("异常通知{0}", joinPoint.getThis()));
    }
}

@Aspect:指定为切面类

XmlAnnotationAopBean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans" 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-4.0.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"
>

    <context:component-scan base-package="XmlAnnotationAopBean"/>
    <aop:aspectj-autoproxy/>

</beans>

aop:aspectj-autoproxy/:开启自动AOP代理

单元测试

import XmlAnnotationAopBean.XmlAnnotationAopBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:XmlAnnotationAopBean.xml")
public class XmlAnnotationAopBeanTest {
    @Autowired
    private XmlAnnotationAopBean xmlAnnotationAopBean;

    @Test
    public void xmlAnnotationAopBeanTest() {
        xmlAnnotationAopBean.runWithArgs(1);
        xmlAnnotationAopBean.runWithoutArgs();
    }
}

输出结果

前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@5965d37
前置通知参数:1
这是有参方法,参数:1
后环绕通知执行类型:method-execution
后置通知方法:void XmlAnnotationAopBean.XmlAnnotationAopBean.runWithArgs(Integer)
最终通知目标类:XmlAnnotationAopBean.XmlAnnotationAopBean@38467116
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@5b7a7f33
前置通知参数:{0}
这是无参方法。
后环绕通知执行类型:method-execution
后置通知方法:void XmlAnnotationAopBean.XmlAnnotationAopBean.runWithoutArgs()
最终通知目标类:XmlAnnotationAopBean.XmlAnnotationAopBean@38467116

纯注解

新建配置注解类BaseConfig、实体类AnnotationAopBean和AOP类AnnotationAopService

注解配置BaseConfig

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = "AnnotationAopBean")
@EnableAspectJAutoProxy
public class BaseConfig {
}

@EnableAspectJAutoProxy:开启自动AOP代理

实体类AnnotationAopBean

package AnnotationAopBean;

import org.springframework.stereotype.Component;

import java.text.MessageFormat;

@Component
public class AnnotationAopBean {

    public void runWithoutArgs() {
        System.out.println("这是无参方法。");
    }

    public void runWithArgs(Integer arg) {
        Integer i = 1 / arg;
        System.out.println(MessageFormat.format("这是有参方法,参数:{0}", arg));
    }
}


AOP类AnnotationAopService

package AnnotationAopBean;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;

@Component
@Aspect
public class AnnotationAopService {


    @Pointcut("execution(void AnnotationAopBean.*(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("前置通知参数:{0}", joinPoint.getArgs()));
    }

    @After("pointCut()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("后置通知方法:{0}", joinPoint.getSignature()));
    }

    @AfterReturning("pointCut()")
    public void doEnd(JoinPoint joinPoint) {
        System.out.println(MessageFormat.format("最终通知目标类:{0}", joinPoint.getTarget()));
    }

    @Around("pointCut()")
    public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println(MessageFormat.format("前环绕通知代码位置:{0}", proceedingJoinPoint.getSourceLocation()));
        proceedingJoinPoint.proceed();
        System.out.println(MessageFormat.format("后环绕通知执行类型:{0}", proceedingJoinPoint.getKind()));
    }
    
    @AfterThrowing("pointCut()")
    public void doAfterThrow(JoinPoint joinPoint){
        System.out.println(MessageFormat.format("异常通知{0}", joinPoint.getThis()));
    }
}

单元测试

import AnnotationAopBean.AnnotationAopBean;
import XmlAopBean.XmlAopBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {BaseConfig.class})
public class AOPBeanTest {
    @Autowired
    private AnnotationAopBean annotationAopBean;

    @Test
    public void annotationAopBeanTest() {
        annotationAopBean.runWithArgs(1);
        annotationAopBean.runWithoutArgs();
    }
    
    ....
}

输出结果

前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@5f9edf14
前置通知参数:1
这是有参方法,参数:1
后环绕通知执行类型:method-execution
后置通知方法:void AnnotationAopBean.AnnotationAopBean.runWithArgs(Integer)
最终通知目标类:AnnotationAopBean.AnnotationAopBean@68746f22
前环绕通知代码位置:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@2f01783a
前置通知参数:{0}
这是无参方法。
后环绕通知执行类型:method-execution
后置通知方法:void AnnotationAopBean.AnnotationAopBean.runWithoutArgs()
最终通知目标类:AnnotationAopBean.AnnotationAopBean@68746f22

源码下载

git@github.com:Angryshark128/Practice.git

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值