例子
Spring 配置文件
<?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" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <context:component-scan base-package="com.benx.mvc" /> <bean class="com.benx.aspectj.service.HelloImpl" /> <bean id="monitor" class="com.benx.aspectj.HelloMonitor" /> <aop:config> <aop:aspect id="helloMonitor" ref="monitor"> <aop:pointcut id="businessService" expression="execution(* com.benx.aspectj.service.*.*(..))" /> <aop:before pointcut-ref="businessService" method="before" /> <aop:after pointcut-ref="businessService" method="after" /> <aop:after-returning pointcut-ref="businessService" method="afterReturning" returning="result" /> <aop:after-throwing pointcut-ref="businessService" method="afterThrowing" throwing="ex" /> <aop:around pointcut-ref="businessService" method="around"/> </aop:aspect> </aop:config> </beans>
接口类
package com.benx.aspectj.service; public interface IHello { public String say(); }
接口实现类
package com.benx.aspectj.service; public class HelloImpl implements IHello { public String say() { String msg = "Hello World"; System.out.println(msg); return msg; } }
监听器
package com.benx.aspectj; import org.aspectj.lang.ProceedingJoinPoint; public class HelloMonitor { public void before() { System.out.println("start"); } public void after() { System.out.println("end"); } public void afterReturning(Object result) { System.out.println("afterReturning "); System.out.println(result); } public void afterThrowing(Exception ex) { System.out.println("afterThrowing" + ex.getMessage()); } public Object around(ProceedingJoinPoint call) { System.out.println("around start"); Object ob = null; try { ob = call.proceed(); } catch (Throwable e) { e.printStackTrace(); } finally { System.out.println("around end"); } return ob; } }
测试类
package com.benx.aspectj; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.benx.aspectj.service.IHello; public class Test { /** * @param args */ public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/benx/aspectj/aspectj_spring.xml"); IHello hello = context.getBean(IHello.class); hello.say(); } }
执行结果:
start
around start
Hello World
around end
afterReturning
Hello World
end
实现原理:
xml的命名空间aop的解析类ConfigBeanDefinitionParser负责解析,步骤:
1、先注入AspectJAwareAdvisorAutoProxyCreator到spring context中,该类生成代理类
2、解析aop:pointcut 代表匹配路径
3、解析 aop:before aop:after 代表拦截器,每个拦截器包含了pointcut(过滤器表达式)和Method
生成代理流程,执行AspectJAwareAdvisorAutoProxyCreator的postProcessAfterInitialization方法,该方法在bean执行init方法后执行,然后遍历所有拦截器,根据拦截器的pointcut表达式来判断该Bean是否在拦截范围之内,如果在,则生成代理对象,把匹配的拦截器也加入到代理对象中。