【第12章】spring-aop-xml版


前言

Spring AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的一个重要模块,它提供了一种将横切关注点(cross-cutting concerns)从业务逻辑中分离出来的方法。横切关注点通常包括日志记录、事务管理、安全性等,这些关注点经常散落在代码的各个角落,导致代码重复和难以维护。

通过使用Spring AOP,你可以将这些横切关注点定义为切面(Aspect),然后将它们织入(weave)到目标对象的方法执行流程中。这样,你可以在不影响业务逻辑的前提下,添加或修改横切关注点的行为。

Spring AOP主要使用代理模式来实现,它为目标对象创建一个代理对象,并在代理对象上拦截方法调用。当方法被调用时,代理对象会根据切面的配置来决定是否执行额外的操作(如日志记录、事务管理等)。

Spring AOP的主要特点包括:

  1. 声明式编程:你可以通过注解或XML配置文件来声明切面、切点和通知(advice),而无需修改业务代码。
  2. 集成性强:Spring AOP与Spring的其他模块(如Spring MVC、Spring Data等)无缝集成,可以轻松地在Spring应用中实现面向切面编程。
  3. 可扩展性:你可以自定义切面、切点和通知的实现,以满足特定的业务需求。

需要注意的是,Spring AOP是基于代理的,因此它只能拦截通过Spring容器管理的bean之间的方法调用。对于非Spring管理的对象或方法(如静态方法、私有方法等),Spring AOP可能无法提供支持。如果需要更强大的AOP功能,可以考虑使用AspectJ等更专业的AOP框架。


一、准备

1. service

package org.example.aop.xml;

/**
 * Create by zjg on 2024/4/14
 */
public interface Calculator {
    int add(int i,int j);
    int sub(int i,int j);
    int mul(int i,int j);
    int div(int i,int j);
}

2. impl

package org.example.aop.xml.impl;

import org.example.aop.xml.Calculator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Create by zjg on 2024/4/14
 */
public class CalculatorImpl implements Calculator {
    private Logger logger = LoggerFactory.getLogger(CalculatorImpl.class);
    @Override
    public int add(int i, int j) {
        logger.debug("add({},{})",i,j);
//        int s=1/0;
        return i+j;
    }

    @Override
    public int sub(int i, int j) {
        logger.debug("sub({},{})",i,j);
        return i-j;
    }

    @Override
    public int mul(int i, int j) {
        logger.debug("mul({},{})",i,j);
        return i*j;
    }

    @Override
    public int div(int i, int j) {
        logger.debug("div({},{})",i,j);
        return i/j;
    }
}

二、核心代码

1. 切面类

package org.example.aop.xml.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;

/**
 * Create by zjg on 2024/4/14
 */
@Component
@Aspect
public class LogAspect {
    private Logger logger = LoggerFactory.getLogger(LogAspect.class);
    public void before(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        logger.debug("[{}前置通知]{}",name, Arrays.toString(args));
    }
    public void afterReturning(JoinPoint joinPoint,Object result){
        String name = joinPoint.getSignature().getName();
        logger.debug("[{}返回通知][{}]",name,result);
    }
    public void afterThrowing(JoinPoint joinPoint,Exception exception){
        String name = joinPoint.getSignature().getName();
        logger.debug("[{}异常通知][{}]",name,exception.getMessage());
    }
    public void after(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        logger.debug("[{}后置通知]",name);
    }
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        logger.debug("[{}环绕通知前置]{}",name,Arrays.toString(args));
        Object result = null;
        try {
            result= joinPoint.proceed();
            logger.debug("[{}环绕通知返回][{}]",name,result);
        }catch (Exception exception){
            logger.debug("[{}环绕通知异常]",name);
        }finally {
            logger.debug("[{}环绕通知后置]",name);
        }
        return result;
    }
}

2. 配置文件

<?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">
    <bean id="calculator" class="org.example.aop.xml.impl.CalculatorImpl"></bean>
    <bean id="logAspect" class="org.example.aop.xml.aspect.LogAspect"></bean>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <aop:config>
        <aop:aspect id="logAspect" ref="logAspect">
            <aop:pointcut id="pointcut" expression="execution(* org.example.aop.xml.*.*(..))"/>
            <aop:before method="before" pointcut-ref="pointcut"></aop:before>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"></aop:after-returning>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="exception"></aop:after-throwing>
            <aop:after method="after" pointcut-ref="pointcut"></aop:after>
            <aop:around method="around" pointcut-ref="pointcut"></aop:around>
        </aop:aspect>
    </aop:config>
</beans>

3. 测试类

package org.example.aop.xml;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Create by zjg on 2024/4/14
 */
public class Test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springContext.xml");
        Calculator calculator = context.getBean("calculator", Calculator.class);
        calculator.add(1,1);
    }
}

4. 测试结果

[2024-04-14 14:17:20.384][main][DEBUG]- org.example.aop.xml.aspect.LogAspect.before(LogAspect.java:27) - [add前置通知][1, 1]
[2024-04-14 14:17:20.385][main][DEBUG]- org.example.aop.xml.aspect.LogAspect.around(LogAspect.java:44) - [add环绕通知前置][1, 1]
[2024-04-14 14:17:20.385][main][DEBUG]- org.example.aop.xml.impl.CalculatorImpl.add(CalculatorImpl.java:14) - add(1,1)
[2024-04-14 14:17:20.385][main][DEBUG]- org.example.aop.xml.aspect.LogAspect.around(LogAspect.java:48) - [add环绕通知返回][2]
[2024-04-14 14:17:20.385][main][DEBUG]- org.example.aop.xml.aspect.LogAspect.around(LogAspect.java:52) - [add环绕通知后置]
[2024-04-14 14:17:20.386][main][DEBUG]- org.example.aop.xml.aspect.LogAspect.after(LogAspect.java:39) - [add后置通知]
[2024-04-14 14:17:20.386][main][DEBUG]- org.example.aop.xml.aspect.LogAspect.afterReturning(LogAspect.java:31) - [add返回通知][2]

总结

回到顶部

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值