一、AOP代码准备
aop.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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- <bean class="com.mashibing.MyBeanFactoryPostProcessorBySelf" ></bean>-->
<bean id="logUtil" class="com.mashibing.aop.xml.util.LogUtil" ></bean>
<bean id="myCalculator" class="com.mashibing.aop.xml.service.MyCalculator" ></bean>
<aop:config>
<aop:aspect ref="logUtil">
<aop:pointcut id="myPoint" expression="execution( Integer com.mashibing.aop.xml.service.MyCalculator.* (..))"/>
<aop:around method="around" pointcut-ref="myPoint"></aop:around>
<aop:before method="start" pointcut-ref="myPoint"></aop:before>
<aop:after method="logFinally" pointcut-ref="myPoint"></aop:after>
<aop:after-returning method="stop" pointcut-ref="myPoint" returning="result"></aop:after-returning>
<aop:after-throwing method="logException" pointcut-ref="myPoint" throwing="e"></aop:after-throwing>
</aop:aspect>
</aop:config>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
以上是常规xml配置aop文件准备,下面是具体的切面java类准备。
package com.mashibing.aop.xml.util;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import java.util.Arrays;
//@Aspect
//@Component
//@Order(200)
public class LogUtil {
// @Pointcut("execution(public Integer com.mashibing.service.MyCalculator.*(Integer,Integer))")
public void myPointCut(){}
// @Pointcut("execution(* *(..))")
public void myPointCut1(){}
// @Before(value = "myPointCut()")
private int start(JoinPoint joinPoint){
//获取方法签名
Signature signature = joinPoint.getSignature();
//获取参数信息
Object[] args = joinPoint.getArgs();
System.out.println("log---"+signature.getName()+"方法开始执行:参数是"+Arrays.asList(args));
return 100;
}
// @AfterReturning(value = "myPointCut()",returning = "result")
public static void stop(JoinPoint joinPoint,Object result){
Signature signature = joinPoint.getSignature();
System.out.println("log---"+signature.getName()+"方法执行结束,结果是:"+result);
}
// @AfterThrowing(value = "myPointCut()",throwing = "e")
public static void logException(JoinPoint joinPoint,Exception e){
Signature signature = joinPoint.getSignature();
System.out.println("log---"+signature.getName()+"方法抛出异常:"+e.getMessage());
}
// @After("myPointCut()")
public static void logFinally(JoinPoint joinPoint){
Signature signature = joinPoint.getSignature();
System.out.println("log---"+signature.getName()+"方法执行结束。。。。。over");
}
// @Around("myPointCut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Signature signature = pjp.getSignature();
Object[] args = pjp.getArgs();
Object result = null;
try {
System.out.println("log---环绕通知start:"+signature.getName()+"方法开始执行,参数为:"+Arrays.asList(args));
//通过反射的方式调用目标的方法,相当于执行method.invoke(),可以自己修改结果值
result = pjp.proceed(args);
// result=100;
System.out.println("log---环绕通知stop"+signature.getName()+"方法执行结束");
} catch (Throwable throwable) {
System.out.println("log---环绕异常通知:"+signature.getName()+"出现异常");
throw throwable;
}finally {
System.out.println("log---环绕返回通知:"+signature.getName()+"方法返回结果是:"+result);
}
return result;
}
}
以上的例子就比较简单,就是在xml里面配置对应的aop切点、切面,接下来我们看下在spring AOP源码中是如何运行的。
二、Spring AOP 配置文件解析
在之前的spring 标签解析源码中我们有介绍到spring 配置文件解析是在refresh方法中,具体可见:Spring源码解析(15)之refresh源码分析(三)配置文件解析_refresh本地配置文件-CSDN博客文章浏览阅读476次。一、前言在前面的博客中我们有介绍到refresh方法中的otainFreshBeanFaction方法,这个方法的作用就是获取bean工厂,在这期间还会完成配置文件的加载,生成BeanDefinition,需要注意的是这里生成的BeanFactory默认的是DefaultListableBeanFactory,需要注意的是,我们自定的一些xsd约束文件也是在这里完成解析,通过实现BeanDefitionParser接口,并且实现parse方法,自定义的标签也通过实现NamespaceHan