Hey, Nice to meet You. 

必有过人之节.人情有所不能忍者,匹夫见辱,拔剑而起,挺身而斗,此不足为勇也,天下有大勇者,猝然临之而不惊,无故加之而不怒.此其所挟持者甚大,而其志甚远也.          ☆☆☆所谓豪杰之士,

基于XML的方式实现AOP

1、XML配置相关元素

我们知道注解很方便,并且是很强大的东西,并且在平时的开发中基本都会使用注解开发,但基于 XML 的方式我们仍然需要了解,其实就跟注解差不多的功能,只是换了一种形式,下面先来了解一下 AOP 中可以配置的元素:

AOP 配置元素 用途
aop:advisor 定义 AOP 的通知其(一种很古老的方式,很少使用)
aop:aspect 定义一个切面
aop:before 定义前置通知
aop:after 定义后置通知
aop:around 定义环绕通知
aop:after-returning 定义返回通知
aop:after-throwing 定义异常通知
aop:config 顶层的 AOP 配置元素。大多数的<aop:*>元素必须包含在<aop:config>中
aop:declare-parents 给通知引入新的额外接口,增强功能
aop:pointcut 定义切点

2、基于XML配置AOP

[1]、配置applicationContext.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:context="http://www.springframework.org/schema/context"
       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 https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 将被代理的目标类加入IOC容器 -->
    <bean class="com.thr.aop.target.UserServiceImpl" id="userService"/>

    <!-- 将切面类加入IOC容器 -->
    <bean class="com.thr.aop.aspect.LogXmlAspect" id="logXmlAspect"/>

    <!-- 配置AOP -->
    <aop:config>

        <!-- 声明切入点表达式 -->
        <aop:pointcut id="logPointCut" expression="execution(* *..*.*(..))"/>

        <!-- 配置切面,使用ref属性引用切面类对应的bean。如有需要可以使用order属性指定当前切面的优先级数值 -->
        <aop:aspect ref="logXmlAspect">
            <!-- 配置具体通知方法,通过pointcut-ref属性引用上面已声明的切入点表达式 -->
            <aop:before method="doBefore" pointcut-ref="logPointCut"/>

            <!-- 在返回通知中使用returning属性指定接收方法返回值的变量名 -->
            <aop:after-returning method="doAfterReturning" pointcut-ref="logPointCut" returning="returnValue"/>

            <!-- 在异常通知中使用throwing属性指定接收异常对象的变量名 -->
            <aop:after-throwing method="doAfterThrowing" pointcut-ref="logPointCut" throwing="throwable"/>

            <!-- 配置后置帖子 -->
            <aop:after method="doAfter" pointcut-ref="logPointCut"/>
        </aop:aspect>

    </aop:config>
</beans>

[2]、创建目标接口

/**
 * 目标类接口
 */
public interface IUserService {

    void addUser(String userName,Integer age);
}

[3]、创建目标接口实现类

/**
 * 目标类,会被动态代理
 */
@Service
public class UserServiceImpl implements IUserService {

    @Override
    public void addUser(String userName, Integer age) {
        System.out.println(userName + ":" + age);
    }
}

[4]、创建切面类

/**
 * 创建日志切面类
 */
public class LogXmlAspect {
    
    public void doBefore(JoinPoint joinPoint) { // 在通知方法中,声明JoinPoint类型的形参,就可以在Spring调用当前方法时把这个类型的对象传入

        // 1.通过JoinPoint对象获取目标方法的签名
        // 所谓方法的签名就是指方法声明时指定的相关信息,包括方法名、方法所在类等等
        Signature signature = joinPoint.getSignature();

        // 2.通过方法签名对象可以获取方法名
        String methodName = signature.getName();

        // 3.通过JoinPoint对象获取目标方法被调用时传入的参数
        Object[] args = joinPoint.getArgs();

        // 4.为了方便展示参数数据,把参数从数组类型转换为List集合
        List<Object> argList = Arrays.asList(args);

        System.out.println("[前置通知]" + methodName + "方法开始执行,参数列表是:" + argList);
    }

    public void doAfterReturning(JoinPoint joinPoint, Object returnValue) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[返回通知]" + methodName + "方法成功结束,返回值是:" + returnValue);
    }
    
    public void doAfterThrowing(JoinPoint joinPoint, Throwable throwable) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[异常通知]" + methodName + "方法异常结束,异常信息是:" + throwable.getMessage());
    }
    
    public void doAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[后置通知]" + methodName + "方法最终结束");
    }
}

[5]、创建测试类

public class XmlAOPTest {

    //创建ApplicationContext对象
    private ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    @Test
    public void testAOP(){
        // 1.从IOC容器中获取接口类型的对象
        IUserService userService = ac.getBean(IUserService.class);

        // 2.调用方法查看是否应用了切面中的通知
        userService.addUser("张三",20);
    }
}

[6]、运行结果

image

posted @ 2021-05-08 20:04  唐浩荣  阅读(714)  评论(0编辑  收藏  举报