在学习aop之前先来解释一下aop一些概念
[list]
[*]Joinpoint:它定义在哪里加入你的逻辑功能,对于Spring AOP,Jointpoint指的就是Method。
[*]Advice:特定的Jointpoint处运行的代码,对于Spring AOP 来讲,有Before advice、AfterreturningAdvice、ThrowAdvice、AroundAdvice(MethodInteceptor)等。
[*]Pointcut:一组Joinpoint,就是说一个Advice可能在多个地方织入,
[*]Aspect:实际是Advice和Pointcut的组合,但是Spring AOP 中的Advisor也是这样一个东西,但是Spring中为什么叫Advisor而不叫做Aspect。
[*]Target:被通知的对象。
[*]Proxy:将通知应用到目标对象后创建的对象
[*]Weaving:将Aspect加入到程序代码的过程,对于Spring AOP,由ProxyFactory或者ProxyFactoryBean负责织入动作。
[/list]
spring对AOP的支持有以下4种情况:
[list]
[*]经典的基于代理的aop(各版本spring)
[*]@AspectJ注解驱动的切面(spring2.0后)
[*]纯pojo切面(spring2.0后)
[*]注入式AspectJ切面(各版本spring)
[/list]
ITarget.java
TargetImpl.java
创建通知
Advice .java
TargetException .java
使用自动代理@AspectJ切面时,需要先注册一个切面AspectAdvice.java
AdviceBean.java
applicationContext.xml
TestSpringAop.java
[list]
[*]Joinpoint:它定义在哪里加入你的逻辑功能,对于Spring AOP,Jointpoint指的就是Method。
[*]Advice:特定的Jointpoint处运行的代码,对于Spring AOP 来讲,有Before advice、AfterreturningAdvice、ThrowAdvice、AroundAdvice(MethodInteceptor)等。
[*]Pointcut:一组Joinpoint,就是说一个Advice可能在多个地方织入,
[*]Aspect:实际是Advice和Pointcut的组合,但是Spring AOP 中的Advisor也是这样一个东西,但是Spring中为什么叫Advisor而不叫做Aspect。
[*]Target:被通知的对象。
[*]Proxy:将通知应用到目标对象后创建的对象
[*]Weaving:将Aspect加入到程序代码的过程,对于Spring AOP,由ProxyFactory或者ProxyFactoryBean负责织入动作。
[/list]
spring对AOP的支持有以下4种情况:
[list]
[*]经典的基于代理的aop(各版本spring)
[*]@AspectJ注解驱动的切面(spring2.0后)
[*]纯pojo切面(spring2.0后)
[*]注入式AspectJ切面(各版本spring)
[/list]
ITarget.java
package com.myspring.aop;
public interface ITarget {
public void execute() throws TargetException;
}
TargetImpl.java
package com.myspring.aop;
public class TargetImpl implements ITarget {
public TargetImpl() {
}
public void execute() throws TargetException {
System.out.println("main...");
}
}
创建通知
Advice .java
package com.myspring.aop;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
public class Advice implements MethodBeforeAdvice,
AfterReturningAdvice, ThrowsAdvice {
public Advice() {}
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("传统经典aop的before...");
}
public void afterReturning(Object rtn, Method method,
Object[] args, Object target) throws Throwable {
System.out.println("传统经典aop的afterReturning...");
}
public void afterThrowing(Throwable throwable) {
System.out.println("传统经典aop的afterThrowing...");
}
public void afterThrowing(Method method, Object[] args, Object target,
Throwable throwable) {
System.out.println("传统经典aop的afterThrowing2...");
}
}
TargetException .java
package com.myspring.aop;
@SuppressWarnings("serial")
public class TargetException extends RuntimeException {
public TargetException() {}
public TargetException(String message) {
super(message);
}
}
使用自动代理@AspectJ切面时,需要先注册一个切面AspectAdvice.java
package com.myspring.aop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect//声明切面
public class AspectAdvice {
@Pointcut("execution(* *.execute(..))")//定义切点,匹配规则为(返回类型 返回类.方法(参数设置)
public void todo(){}
@Before("todo()")
public void before() {
System.out.println("自动代理@AspectJ切面before...");
}
@AfterReturning("todo()")
public void afterReturning() {
System.out.println("自动代理@AspectJ切面afterReturning...");
}
@AfterThrowing("todo()")
public void afterThrowing() {
System.out.println("自动代理@AspectJ切面afterThrowing...");
}
}
AdviceBean.java
package com.myspring.aop;
public class AdviceBean {
public void before() {
System.out.println("纯POJO切面before...");
}
public void afterReturning() {
System.out.println("纯POJO切面afterReturning...");
}
public void afterThrowing() {
System.out.println("纯POJO切面afterThrowing...");
}
}
applicationContext.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<!-- 当定义一个纯粹的POJO切面时,创建此Bean -->
<bean id="adviceBean" class="com.myspring.aop.AdviceBean"></bean>
<!-- 利用spring AOP的配置元素定义一个通知 -->
<aop:config>
<!-- 引用刚才定义的一个纯粹的POJO切面Bean -->
<aop:aspect ref="adviceBean">
<!-- 定义一个命名切点,必点切点定义的重复,expression用于配置匹配规则,(返回类型 返回类.方法(参数设置) -->
<aop:pointcut id="todo" expression="execution(* com.myspring.aop.TargetImpl.execute(..))" />
<!-- 方法前通知 -->
<aop:before method="before" pointcut-ref="todo" />
<aop:after-returning method="afterReturning" pointcut-ref="todo" />
<aop:after-throwing method="afterThrowing" pointcut-ref="todo"/>
</aop:aspect>
</aop:config>
<!-- ************************************** -->
<bean id="aspectAdvice" class="com.myspring.aop.AspectAdvice"></bean>
<!-- 当使用自动代理@AspectJ切面时,需要定义自动配置元素,在原来的xml文件的beans中加入xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd,具体位置如上 -->
<aop:aspectj-autoprox />
<!-- ************************************** -->
<!-- 以下为传统的aop代理 -->
<!-- 定义一个bean -->
<bean id="target" class="com.myspring.aop.TargetImpl">
</bean>
<!-- 定义一个通知bean -->
<bean id="advice" class="com.myspring.aop.Advice">
</bean>
<!-- 正则表达式切入点 -->
<bean id="jdkRegexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="advice" />
<property name="pattern" value=".*execute" />
</bean>
<!-- AspectJ切点 -->
<bean id="aspectjPointcut" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="advice" ref="advice" /> <property name="expression"
value="execution(* *.execute(..))" /> </bean>
<!-- 使用ProxyFactoryBean工厂,用于生成一个代理,把一个或多个拦截者(和通知者)应用到Bean -->
<bean id="myAop" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="target" />
<property name="proxyInterfaces" value="com.myspring.aop.ITarget" />
<property name="interceptorNames" value="jdkRegexpAdvisor" />
</bean>
<!-- 创建自动代理,会自动检查通知者的切点是否匹配bean的方法,并且使用通知的代理来替换这个bean定义 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
</beans>
TestSpringAop.java
package com.myspring.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpringAop {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//使用经典的aop
ITarget target = (ITarget) ctx.getBean("myAop");
//使用自动代理,可以直接调用目标对象
ITarget autotarget = (ITarget) ctx.getBean("target");
target.execute();
}
}