目录
3.2 bean配置文件: bean_aop_around.xml
4.2 bean配置文件: bean_aop_around2.xml
1. 要求
之前完成了通过@Before和@After的方式,完成了对类UserServiceImpl中的search方法的aop操作 ,这里要求:通过@Aspect注解的方式实现对UserServiceImpl的aop的@Around操作!
前文:
Java练习(十):Spring应用之AOP的@Before, @After操作(简单工程示例)
2. 涉及的知识点
@Before, @After, @Around三者之前的关系:
@Before 是在所拦截方法执行之前执行一段逻辑。
@After 是在所拦截方法执行之后执行一段逻辑。
@Around 是可以同时在所拦截方法的前后执行一段逻辑。
简言之,@Around就包含了@Before和@After两个操作。
3. 示例工程 (第一种方式)
3.1 maven的配置文件: pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>MySpringAOPAround</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3.2 bean配置文件: bean_aop_around.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:annotation-config/>
<!--注册bean-->
<bean id="userService" class="com.my.spring.aop.around.UserServiceImpl"/>
<bean id="aroundLog" class="com.my.spring.aop.around.AroundLog"/>
<!-- <bean id="beforeLog" class="com.my.spring.aop.around.BeforeLog"/>-->
<!-- <bean id="afterLog" class="com.my.spring.aop.around.AfterLog"/>-->
<!--aop的配置-->
<aop:config>
<!--切入点 expression:表达式匹配要执行的方法-->
<aop:pointcut id="pointcut" expression="execution(* com.my.spring.aop.around.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="aroundLog" pointcut-ref="pointcut"/>
<!-- <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
<!-- <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>-->
</aop:config>
</beans>
3.3 接口和类的代码
3.3.1 接口:UserService
package com.my.spring.aop.around;
public interface UserService {
public void add();
public void delete();
public void update();
public void search();
}
3.3.2 实现接口的类:UserServiceImpl
package com.my.spring.aop.around;
public class UserServiceImpl implements UserService{
public void add() {
System.out.println("增加用户");
}
public void delete() {
System.out.println("删除用户");
}
public void update() {
System.out.println("更新用户");
}
public void search() {
System.out.println("查询用户");
}
}
3.3.3 AroundLog类:AroundLog
package com.my.spring.aop.around;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class AroundLog implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
System.out.println("环绕通知: " + name + "方法即将开始!");
// 调用目标对象的指定方法
//真正调用目标方法
Object result = invocation.proceed();
System.out.println("环绕通知: " + name + "方法到此结束!");
return result;
}
}
3.4 测试类
package com.my.spring.around.demo;
import com.my.spring.aop.around.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MySpringAOPAroundTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean_aop_around.xml");
UserService userService = (UserService) context.getBean("userService");
userService.search();
}
}
输出结果:
环绕通知: search方法即将开始!
查询用户
环绕通知: search方法到此结束!
4. 示例工程(第二种方式)
用注解标签 @Aspect, @Around。
简言之,就是简化了bean配置文件里的内容,设置语句<aop:aspectj-autoproxy/>自动扫描,在工程中自动查找标签 @Aspect, @Around等。
4.1 maven的配置文件: pom.xml
同3.1,这里不赘述。
4.2 bean配置文件: bean_aop_around2.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:annotation-config/>
<!--注册bean-->
<bean id="annotationPointcut" class="com.my.spring.aop.around.AnnotationPointcut"/>
<bean id="userService2" class="com.my.spring.aop.around.UserServiceImpl"/>
<!-- 简化了bean配置文件里的内容,设置语句<aop:aspectj-autoproxy/>自动扫描 -->
<aop:aspectj-autoproxy/>
</beans>
4.3 接口和类的代码
4.3.1 接口:UserService
package com.my.spring.aop.around;
public interface UserService {
public void add();
public void delete();
public void update();
public void search();
}
4.3.2 实现接口的类:UserServiceImpl
package com.my.spring.aop.around;
public class UserServiceImpl implements UserService{
public void add() {
System.out.println("增加用户2");
}
public void delete() {
System.out.println("删除用户2");
}
public void update() {
System.out.println("更新用户2");
}
public void search() {
System.out.println("查询用户2");
}
}
4.3.3 AnnotationPointcut类:
类似于第一种方法中的AroundLog类,实现环绕效果,方法的调用。
使用注解@Aspect, @Around。
package com.my.spring.aop.around;
// 如果自动扫描<aop:aspectj-autoproxy/>,那么程序肯定找标签
// 在整个工程里找标签,即如果包含多个类文件,多个@Aspect,程序都会找到并执行。
// 但真实的情况下,同一个方法,不会用多个@Around
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class AnnotationPointcut {
/*
@Before("execution(* com.my.demo.aop.UserServiceImpl.*(..))")
public void before(){
System.out.println("---------方法执行前---------");
}
@After("execution(* com.my.demo.aop.UserServiceImpl.*(..))")
public void after(){
System.out.println("---------方法执行后---------");
}
*/
@Around("execution(* com.my.spring.aop.around.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable{
System.out.println("~~~~~~~~~~~~~~~~Around方法执行前~~~~~~~~~~~~~~~~~~~~~");
System.out.println("签名: "+jp.getSignature());
Object proceed = jp.proceed(); //执行目标方法
System.out.println("~~~~~~~~~~~~~~~~Around方法执行后~~~~~~~~~~~~~~~~~~~~~");
}
}
4.4 测试类
package com.my.spring.around.demo;
import com.my.spring.aop.around.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MySpringAOPAroundTest2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean_aop_around2.xml");
UserService userService = (UserService) context.getBean("userService2");
userService.search();
}
}
输出结果:
~~~~~~~~~~~~~~~~Around方法执行前~~~~~~~~~~~~~~~~~~~~~
签名: void com.my.spring.aop.around.UserService.search()
查询用户2
~~~~~~~~~~~~~~~~Around方法执行后~~~~~~~~~~~~~~~~~~~~~