多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
下面实现在执行目标方法`UserService.loadByUsername`之前,先执行`AspectLogger.printLog`方法。 <br/> **1. 创建一个 maven 项目** ```xml <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <spring.version>6.0.11</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.19</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> </dependency> </dependencies> ``` <br/> **2. 一个接口和他的一个实现类** ```java public interface UserService { void loadByUsername(String username); } public class UserServiceImpl implements UserService { /** * 目标函数 * @param username */ @Override public void loadByUsername(String username) { System.out.println("------目标函数的输出------\n[loadByUsername]:" + username); } } ``` <br/> **3. 创建一个切面** ```java public class AspectLogger { /** * 增强函数,在同一个切面中如果存在多个重载的增强函数,即使参数列表不一致 * 默认起作用的始终是第一个增强函数,其它的无效。 */ public void printLog(JoinPoint jPoint) { System.out.println("\n------增强函数的输出------" + "\n增强方式:前置增强" + "\n目标对象:" + jPoint.getTarget() + "\n目标函数:" + jPoint.getSignature().getName() + "\n目标函数的参数:" + Arrays.toString(jPoint.getArgs())); } } ``` <br/> **4. 将相关组件注入到IoC容器中`resources/ApplicationContext.xml`** ```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"> <!-- 目标对象注入 --> <bean id="userService" class="learn.springpgm.service.impl.UserServiceImpl"/> <!-- 切面对象注入 --> <bean id="aspectLogger" class="learn.springpgm.aspect.AspectLogger"/> <!-- 切面配置 --> <aop:config> <!-- 定义切入点 id: 切入点唯一标识 expression: 切入点表达式,只要任一目标函数的定义符合该表达式,就会被做增强处理 --> <aop:pointcut id="loadByUsernamePoint" expression="execution(public void loadByUsername(String))"/> <!-- 定义切面 ref: 上面切面对象的id值 --> <aop:aspect ref="aspectLogger"> <!-- 增强类型:前置增强 method: 增强方法,对应切面对象中的方法,即AspectLogger.printLog方法 pointcut-ref: 引用上面定义的切入点 --> <aop:before method="printLog" pointcut-ref="loadByUsernamePoint"/> </aop:aspect> </aop:config> </beans> ``` <br/> **5. 测试** ```java public class UserTest { private final ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); @Test public void aopTest() { //注意:不能是context.getBean("userService", UserServiceImpl.class); //或context.getBean(UserServiceImpl.class); UserService userService = context.getBean("userService", UserService.class); userService.loadByUsername("zhangsan"); } } ``` 输出结果如下,因为使用的是前置增强,所以增强的输出会在目标函数的输出前面。 ``` ------增强函数的输出------ 增强方式:前置增强 目标对象:learn.springpgm.service.impl.UserServiceImpl@1f9f6368 目标函数:loadByUsername 目标函数的参数:[zhangsan] ------目标函数的输出------ [loadByUsername]:zhangsan ``` **** 案例源码:https://gitee.com/flymini/codes03/tree/master/learn-springpgm