AOP的目的:对类里的方法进行加强
- 前置加强:在方法执行之前加入相关代码
- 后置加强:在方法执行之后加入相关代码
- 环绕加强:在方法执行之前和之后加入相关代码
- 异常加强:在目标方法发生异常时加入相关代码
1,JoinPoint(连接点):所谓连接点是指那些被拦截的点,而spring中这些点就是指方法,因为spring只支持方法类型的连接点。
2,PointCut(切入点):所谓切入点就是指我们要对那些JoinPoint进行拦截的定义。
3,Advice(通知/增强):所谓通知/增强,就是指拦截到JoinPoint后需要完成的事情。他分为前置通知/增强,后置通知/增强,异常通知/增强,最终通知/增强,环绕通知/增强(切面要完成的功能);
4,Introduction(引介)(用的比较少):引介是一种特殊的Advice,在不修改代码的前提下,引介可以在运行期为类动态的添加一些方法或Field。
5,Target(目标):代理对象的目标对象(要增强的类)
6,Weaving(织入):把Advice应用到Target的过程
7,Proxy(代理):一个类被AOP注入增强后,就产生了一个结果代理类
8,Aspect(切面):是PointCut和Advice(Introduction)的结合
通知的种类:
- 前置通知/增强
- 后置通知/增强
- 环绕通知/增强
- 异常通知/增强
- 最终通知/增强
目标类
UserDaoImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.course.dao.impl;
import java.sql.SQLException;
public class UserDaoImpl {
public void addUser(String userName) { System.out.println("Save user, userName = " + userName); }
public void deleteUser(Integer userId) { System.out.println("delete user, userId = " + userId); int[] a = new int[10]; a[10] = 20; }
public void queryUser(Integer userId) { System.out.println("query user, user[userId=" + userId + ", userName=Jerry]"); } }
|
目标类
TimeConsumption.java
1 2 3 4 5 6 7 8 9 10 11 12
| package com.course.experiment;
public class TimeConsumption { public void circulation() { int sum = 0; for (int i = 0; i < 100; i++) { sum = sum + i; } System.out.println("sum = " + sum); } }
|
前置通知
BeforeDMLAdvice.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.course.advice;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeDMLAdvice implements MethodBeforeAdvice{
@Override public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { openTransaction(); } public void openTransaction() { System.out.println("open transaction"); } }
|
后置通知
AfterDMLAdvice.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.course.advice;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class AfterDMLAdvice implements AfterReturningAdvice {
@Override public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { commitTransaction(); }
public void commitTransaction() { System.out.println("commit transaction"); } }
|
环绕通知
TransactionDMLAdvice.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.course.advice;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation;
public class TransactionDMLAdvice implements MethodInterceptor{
@Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { openTransaction(); Object proceed = methodInvocation.proceed(); commitTransaction(); return proceed; } public void openTransaction() { System.out.println("open transaction"); } public void commitTransaction() { System.out.println("commit transaction"); }
}
|
异常通知
MyExceptionAdvice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.course.advice;
import org.springframework.aop.ThrowsAdvice;
public class MyExceptionAdvice implements ThrowsAdvice {
public void afterThrowing(Throwable throwable) throws Exception { System.out.println("产生异常:" + throwable.getMessage()); } }
|
计算程序执行时间(环绕通知)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.course.advice;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation;
public class TimeConsumptionAdvice implements MethodInterceptor {
@Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { long startTime = System.currentTimeMillis(); Object proceed = methodInvocation.proceed(); long endTime = System.currentTimeMillis(); System.out.println("time consumption = " + (endTime - startTime) + " ms"); return proceed; } }
|
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.test;
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.course.dao.impl.UserDaoImpl; import com.course.experiment.TimeConsumption;
public class TestMain {
public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserDaoImpl userDaoImpl = (UserDaoImpl) applicationContext.getBean("myUserDaoImp");
userDaoImpl.addUser("user1");
userDaoImpl.deleteUser(2);
TimeConsumption timeConsumption = (TimeConsumption) applicationContext.getBean("myTimeConsumption"); timeConsumption.circulation(); } }
|
applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <?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/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"> <bean id="myUserDaoImp" class="com.course.dao.impl.UserDaoImpl"></bean> <bean id="myTimeConsumption" class="com.course.experiment.TimeConsumption"></bean> <bean id="myBeforeDMLAdvice" class="com.course.advice.BeforeDMLAdvice"></bean> <bean id="myAfterDMLAdvice" class="com.course.advice.AfterDMLAdvice"></bean> <bean id="myAroundDMLAdvice" class="com.course.advice.TransactionDMLAdvice"></bean> <bean id="MyExceptionAdvice" class="com.course.advice.MyExceptionAdvice"></bean> <bean id="myTimeConsumptionAdvice" class="com.course.advice.TimeConsumptionAdvice"></bean> <aop:config>
<aop:pointcut expression="execution(* com.course.dao.impl.*.*(..))" id="aspect1"/> <aop:pointcut expression="execution(* com.course.experiment.TimeConsumption.circulation(..))" id="aspect2"/>
<aop:advisor advice-ref="myBeforeDMLAdvice" pointcut-ref="aspect1" /> <aop:advisor advice-ref="myAfterDMLAdvice" pointcut-ref="aspect1"/> <aop:advisor advice-ref="myAroundDMLAdvice" pointcut-ref="aspect1"/> <aop:advisor advice-ref="MyExceptionAdvice" pointcut-ref="aspect1"/> <aop:advisor advice-ref="myTimeConsumptionAdvice" pointcut-ref="aspect2"/> </aop:config> </beans>
|
实现环绕通知的两种方式:
- 前置通知+后置通知
- 环绕通知