代码优雅的转变:基于注解的AOP编程在Spring中的实践

简介: 代码优雅的转变:基于注解的AOP编程在Spring中的实践


定义切面类

package world.xuewei.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
/**
 * 自定义切面类
 *
 * @author 薛伟
 * @since 2023/10/23 9:45
 */
@Aspect
public class MyAspect {
    /**
     * 定义切入点方法,方法体内编写额外功能
     * 注解 @Around:用于定义切入点,编写切入点表达式
     */
    @Around(value = "execution(* *(..))")
    public Object around(ProceedingJoinPoint joinPoint) {
        // 在此处编写前置操作
        System.out.println("Before");
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            // 在此处编写异常操作
            System.out.println("Exception");
        }
        // 在此处编写后置操作
        System.out.println("After");
        // 可以在此处编写新的返回值并返回
        return result;
    }
}

Spring 配置文件

<?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 https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 开启 AOP 注解驱动开发 -->
    <aop:aspectj-autoproxy/>
    <!-- 注册原始对象 -->
    <bean id="userService" class="world.xuewei.proxy.UserServiceImpl"/>
    <!-- 注册自定义切面类 -->
    <bean id="around" class="world.xuewei.aspect.MyAspect"/>
</beans>

切入点复用

package world.xuewei.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
/**
 * 自定义切面类
 *
 * @author 薛伟
 * @since 2023/10/23 9:45
 */
@Aspect
public class MyAspect {
    /**
     * 单独定义切入点,只需要关注注解
     */
    @Pointcut("execution(* *(..))")
    public void p1() {
    }
    /**
     * 定义切入点方法,方法体内编写额外功能
     * 注解 @Around:用于定义切入点,编写切入点表达式
     */
    @Around(value = "p1()")
    public Object around(ProceedingJoinPoint joinPoint) {
        // 在此处编写前置操作
        System.out.println("Before");
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            // 在此处编写异常操作
            System.out.println("Exception");
        }
        // 在此处编写后置操作
        System.out.println("After");
        // 可以在此处编写新的返回值并返回
        return result;
    }
    @Around(value = "p1()")
    public Object around1(ProceedingJoinPoint joinPoint) {
        // 在此处编写前置操作
        System.out.println("Before");
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            // 在此处编写异常操作
            System.out.println("Exception");
        }
        // 在此处编写后置操作
        System.out.println("After");
        // 可以在此处编写新的返回值并返回
        return result;
    }
}

强制使用 Cglib 动态代理

<aop:aspectj-autoproxy proxy-target-class="true"/>

坑:代理方法调用

在同一个业务类中,进行业务方法间的调用时,只有最外层的方法才是通过代理对象调用的(加入了额外功能),内部调用的本类的其他方法都是通过原始对象调用,如果想要让内部的方法也通过代理对象调用,那么就需要实现 ApplicationContextAware 接口。

package world.xuewei.proxy;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
 * 用户服务实现
 *
 * @author 薛伟
 * @since 2023/10/18 17:49
 */
public class UserServiceImpl implements UserService, ApplicationContextAware {
    private ApplicationContext context;
    @Override
    public void register() {
        System.out.println("UserServiceImpl.register");
        UserService p = context.getBean(、"userService", UserService.class);
        p.login();
    }
    @Override
    public void login() {
        System.out.println("UserServiceImpl.login");
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}



相关文章
|
4天前
|
Java Spring
|
5天前
|
Java Spring
|
5天前
|
前端开发 Java Maven
Spring AOP
Spring AOP
14 1
|
5天前
|
数据采集 XML 监控
Spring AOP
Spring AOP
29 2
|
9天前
|
Java 开发者 Spring
面向切面编程(SpringAOP)、通过注解实现AOP代码、AOP的工作流程
面向切面编程(SpringAOP)、通过注解实现AOP代码、AOP的工作流程
22 1
面向切面编程(SpringAOP)、通过注解实现AOP代码、AOP的工作流程
|
10天前
|
Java Spring 容器
Spring AOP 代码案例
Spring AOP 代码案例
21 1
|
XML 前端开发 Java
【Spring基础系列3】Spring常用的注解
前两篇文章分别讲解了Sping IOC的基础知识,以及Spring通过注解装配Bean的常用方式,包括@Component、@Repository、@Service、@Controller、@Autowired、@Resource和@Qualifier,这篇文章主要对剩余高频的注解进行讲解。
166 0
【Spring基础系列3】Spring常用的注解
|
XML 前端开发 Java
Spring最常用的36个注解,哪些你还不知道?
随着技术的更新迭代,Java5.0开始支持注解。而作为java中的领军框架spring,自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用注解来控制spring框架。 而spring的的注解那么多,可能做java很多年,都用不上。这里按照类型总结了这7种最常用的注解。 一. 核心注解 @Require 此注解用于bean的setter方法上。表示此属性是必须的,必须在配置阶段注入,否则会抛出BeanInitializationExcepion。 @Autowired 此注解用于bean的field、setter方法以及构造方法上,显式地声明依赖。根据type来autowiring。
Spring最常用的36个注解,哪些你还不知道?
|
XML 前端开发 Java
Spring最常用的36个注解,哪些你还不知道?
36个Spring最常用的7大类注解总结
Spring最常用的36个注解,哪些你还不知道?
|
Java Spring
一张图带你了解——Spring常用注解
spring常用注解 (1).png 参考官网:https://springframework.guru/spring-framework-annotations/
1358 0