AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,因此它有一个专门的编译器用来生成遵照Java字节编码规范的Class文件。java
Spring提供了四种类型的Aop支持
* 基于经典的SpringAOP
* 纯POJO切面
* @ASpectJ注解驱动的切面
* 注入式AspectJ切面(其实与Spring并没有多大的关系,这个就是使用AspectJ这个框架实现Aop编程)spring
其使用ProxyFactoryBean建立:
加强(通知)的类型有:
前置通知:org.springframework.aop.MethodBeforeAdvice
后置通知:org.springframework.aop.AfterReturningAdvice
环绕通知:org.aopalliance.intercept.MethodInterceptor
异常通知:org.springframework.aop.ThrowsAdviceexpress
public interface IBookDao { public int add() public int delete(); } public class BookDaoImpl implements IBookDao{ public int add() { System.out.println("正在添加图书..."); return 0; } public int delete() { System.out.println("正在删除图书..."); return 0; } } //实现了MethodInterceptor的环绕加强类 public class MyAdvice implements MethodInterceptor{ public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("Around Advice before method invocation"); Object o = invocation.proceed(); System.out.println("Around Advice after method invocation"); return o; } }
//将每个链接点都当作切点(拦截每个方法)
<bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean> <bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean> <bean id="bookDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="bookDao"/> <property name="proxyInterfaces" value="com.njust.learning.spring.service.IBookDao"/> <property name="interceptorNames" value="myadvice"/> </bean>
使用RegexMethodPointcutAdvisor针对某些特定的方法进行拦截加强
<bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean> <bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean> <bean id="rmpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <!--patterns,若是有多个指定的值的话,能够使用,隔开,例如value=".*add,.*delete"--> <property name="patterns" value=".*add"/> <property name="advice" ref="myadvice"/> </bean> <!--使用的时候使用这个id,而不是原始的那个id--> <bean id="bookDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="bookDao"/> <property name="proxyInterfaces" value="com.njust.learning.spring.service.IBookDao"/> <property name="interceptorNames" value="rmpAdvisor"/> </bean>
像上面这样,每定义一个dao都须要定义一个ProxyFactoryBean,显得很麻烦,因此咱们引入自动代理,也就是自动建立代理对象编程
<bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean> <bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean> <bean id="rmpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <!--patterns,若是有多个指定的值的话,能够使用,隔开,例如value=".*add,.*delete"--> <property name="patterns" value=".*add"/> <property name="advice" ref="myadvice"/> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames" value="*Dao"></property> <property name="interceptorNames" value="rmpAdvisor"></property> </bean>
<bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean> <bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean> <bean id="rmpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <!--patterns,若是有多个指定的值的话,能够使用,隔开,例如value=".*add,.*delete"--> <property name="patterns" value=".*add"/> <property name="advice" ref="myadvice"/> </bean> <!--根据切面中生成信息生成代理--> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
public interface IBookDao { public int add(); public int delete(); } public class BookDaoImpl implements IBookDao{ public int add() { int a = 1/0; System.out.println("正在添加图书..."); return 0; } public int delete() { System.out.println("正在删除图书..."); return 0; } }
public class PojoAdvice { public void before(){ System.out.println("前置通知"); } public void after(Object returnval){ System.out.println("后置通知"+",处理后的结果为:"+returnval); } public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕前置加强..."); Object o = proceedingJoinPoint.proceed(); System.out.println("环绕后置加强..."); return o; } public void afterThrowing(Throwable e){ System.out.println("异常通知:"+e.getMessage()); } }
<bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean> <bean id="pojoAdvice" class="com.njust.learning.spring.pojoaop.PojoAdvice"></bean> <aop:config> <aop:pointcut id="p" expression="execution (* *.add(..))"/> <aop:aspect ref="pojoAdvice"> <aop:before method="before" pointcut-ref="p"></aop:before> <!--经过设置returning来将返回值传递给通知--> <aop:after-returning method="after" pointcut-ref="p" returning="returnval"/> <aop:around method="around" pointcut-ref="p"/> <!--经过设置returning来将异常对象传递给通知--> <aop:after-throwing method="afterThrowing" pointcut-ref="p" throwing="e"/> </aop:aspect> </aop:config>
咱们借助于Spring Aop的命名空间能够将纯POJO转换为切面,实际上这些POJO只是提供了知足切点的条件时所须要调用的方法,可是,这种技术须要XML进行配置,不能支持注解
因此spring借鉴了AspectJ的切面,以提供注解驱动的AOP,本质上它依然是Spring基于代理的AOP,只是编程模型与AspectJ彻底一致,这种风格的好处就是不须要使用XML进行配置markdown