Table of contents
2. Add annotations to classes and methods
4. Unified configuration pointcut for all methods under a class
2. Native Spring implements AOP
2. Write Spring AOP notification class
3. Write configuration class bean2.xml
Related readings of previous columns & articles
1. Annotate configuration AOP
Spring can use annotations instead of configuration files to configure aspects:
1. Enable annotation support
Enable AOP annotation support in xml
The following is the bean1.xml file
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 扫描包 --> <context:component-scan base-package="com.example"></context:component-scan> <!-- 开启注解配置Aop --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
2. Add annotations to classes and methods
Add the annotation @Aspect above the notification class: configuration aspect
Add annotations above the notification method
- @Before: pre-advice
- @AfterReturning: post notification
- @AfterThrowing: exception notification
- @After: final notice
- @Around: around notifications
MyAspectAdvice advice class
package com.example.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspectJAdvice {
// 后置通知
@AfterReturning("execution(* com.example.dao.UserDao.*(..))")
public void myAfterReturning(JoinPoint joinPoint){
System.out.println("切点方法名:"+joinPoint.getSignature().getName());
System.out.println("目标对象:"+joinPoint.getTarget());
System.out.println("打印日志···"+joinPoint.getSignature().getName()+"方法被执行了!");
}
// 前置通知
@Before("execution(* com.example.dao.UserDao.*(..))")
public void myBefore(){
System.out.println("前置通知···");
}
// 异常通知
@AfterThrowing(value = "execution(* com.example.dao.UserDao.*(..))",throwing = "e")
public void myAfterThrowing(Exception e){
System.out.println("异常通知···");
System.out.println(e.getMessage());
}
// 最终通知
@After("execution(* com.example.dao.UserDao.*(..))")
public void myAfter(){
System.out.println("最终通知···");
}
// 环绕通知
@Around("execution(* com.example.dao.UserDao.*(..))")
public Object myAround(ProceedingJoinPoint point) throws Throwable {
System.out.println("环绕前···");
// 执行方法
Object obj = point.proceed();
System.out.println("环绕后···");
return obj;
}
}
3. Test
Test Methods
// 测试注解开发AOP
@Test
public void testAdd2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("bean1.xml");
UserDao userDao = (UserDao) ac.getBean("userDao");
//userDao.update();
userDao.delete();
}
Test results (no exceptions):
Use the update method to test the result (with exception):
It can be seen that there is no printing after wrapping, because the program is terminated abnormally at this time
4. Unified configuration pointcut for all methods under a class
How to uniformly configure pointcuts for all methods under a class:
Add a method configuration pointcut in the notification class
// 添加方法配置切点 @Pointcut("execution(* com.example.dao.UserDao.*(..))") public void pointcut(){ }
To use the defined pointcut on the notification method, just replace the content in the annotation brackets with "pointCut()" .
2. Native Spring implements AOP
In addition to AspectJ, Spring supports AOP natively. But it should be noted that there are only four types of notifications in the native way to implement AOP: pre-notification, post-notification, surround notification, and exception notification. Final notice missing.
1. Introduce dependencies
<!-- AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.13</version>
</dependency>
2. Write Spring AOP notification class
When Spring natively implements AOP, only four notification types are supported:
notification type implement the interface advance notice MethodBeforeAdvice post notification AfterReturningAdvice Exception notification ThrowsAdvice surround notification MethodInterceptor
package com.example.aspect;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
public class SpringAop implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice, MethodInterceptor {
/**
* 环绕通知
* @param invocation 目标方法
* @return
* @throws Throwable
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("环绕前");
Object proceed = invocation.proceed();
System.out.println("环绕后");
return proceed;
}
/**
* 后置通知
* @param returnValue 目标方法的返回值
* @param method 目标方法
* @param args 目标方法的参数列表
* @param target 目标对象
* @throws Throwable
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("后置通知");
}
/**
* 前置通知
* @param method 目标方法
* @param args 目标方法的参数列表
* @param target 目标对象
* @throws Throwable
*/
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知");
}
/**
* 异常通知
* @param e 异常对象
*/
public void afterThrowing(Exception e){
System.out.println("发生异常了!");
}
}
3. Write configuration class bean2.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.example"></context:component-scan>
<!-- 通知对象 -->
<bean id="springAop" class="com.example.aspect.SpringAop"/>
<!-- 配置代理对象 -->
<bean id="userDaoProxy"class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 配置目标对象 -->
<property name="target" ref="userDao"/>
<!-- 配置通知 -->
<property name="interceptorNames">
<list>
<value>springAop</value>
</list>
</property>
<!-- 代理对象的生成方式 true:使用CGLib false:使用原生JDK生成 -->
<property name="proxyTargetClass" value="true"/>
<!-- bug -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</bean>
</beans>
4 tests
Test class UserDaoTest2
import com.example.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class userDaoTest2 {
// 原生AOP测试
@Test
public void testAdd(){
ApplicationContext ac = new ClassPathXmlApplicationContext("bean2.xml");
UserDao userDao = (UserDao) ac.getBean("userDaoProxy");
userDao.update();
}
}
Test Results
OK, here's a surprise, if you hit here classmate, you'll know
In fact, the bug in the label is because the native method configuration class can only be identified by adding that label, otherwise an error will be reported.
3. SchemaBased realizes AOP
The SchemaBased (basic mode) configuration method refers to using the Spring native method to define notifications, and using the AspectJ framework to configure aspects. So the notification class here is the same as above, just look at the above.
1. Configuration aspect
aop3.xml configuration file
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.example"></context:component-scan>
<!-- 通知对象 -->
<bean id="springAop2" class="com.example.aspect.SpringAop"/>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut id="myPointcut" expression="execution(* com.example.dao.UserDao.*(..))"/>
<!-- 配置切面:advice-ref:通知对象 pointcut-ref:切点 -->
<aop:advisor advice-ref="springAop2" pointcut-ref="myPointcut"/>
</aop:config>
</beans>
2. Test
Test Methods
// 使用AspectJ框架配置切面测试
@Test
public void t6(){
ApplicationContext ac = new ClassPathXmlApplicationContext("aop3.xml");
UserDao userDao = (UserDao) ac.getBean("userDao");
userDao.add();
}
Test Results
OK, the output here should be that what I defined above is not perfect, and some may have been defined repeatedly, so here are some things that are repeatedly output
Related readings of previous columns & articles
If you don’t know anything about the content of this issue, you can also go to see the content of previous issues. The following is a series of column articles such as Maven and Mybatis carefully crafted by bloggers in the past. Don’t miss it when you pass by! If it is helpful to you, please like it and bookmark it. Among them, some of the Spring columns are being updated, so they cannot be viewed, but they can be viewed after the bloggers have completed all the updates.
1. Maven series of columns
Maven Series Column | Maven project development |
Maven aggregation development [example detailed explanation --- 5555 words] |