一、Spring AOP 的相关术语
- Joinpoint:连接点;指那些被拦截到的点。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点。
- Pointcut:切入点;指我们要对哪些“Joinpoint”进行拦截的定义。
- Aspect:切面;是切入点和通知(引介)的集合;时间、地点和要发生的“故事”。
- Advice:通知;指拦截到“Joinpoint”之后所要做的事情,
- Before:前置通知
- After-returning:后置通知
- After-throwing:异常通知
- Arround:环绕通知
- Introdution:引介;引介是一种特殊的通知,在不修改类代码的前提下,Introdution可以在运行期为类动态的添加一些方法或属性。
- Target:目标;目标对象,要增强的类。
- Proxy:代理;一个类被AOP织入增强后,就产生一个结果代理类。
- Weaving:织入;是把增强应用到目标的过程;把Advice应用到Target的过程。
二、Spring AOP 基本jar包
- spring-beans-4.3.9.RELEASE.jar
- spring-context-4.3.9.RELEASE.jar
- spring-core-4.3.9.RELEASE.jar
- spring-expression-4.3.9.RELEASE.jar
- spring-aspects-4.3.9RELEASE.jar
- aopalliance-1.0.jar
- aspectjweaver-1.8.4.jar
- commons-logging-1.1.1.jar
- log4j-1.2.14.jar
三、aspectj的XML方式实现AOP
package com.sitech.test11;
public class Book {
public void look() {
System.out.println(getClass().getName() + ".look()");
}
}
package com.sitech.test11;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyBook {
public void before() {
System.out.println(getClass().getName() + ".before()");
}
public void after() {
System.out.println(getClass().getName() + ".after()");
}
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("方法之前");
proceedingJoinPoint.proceed();
System.out.println("方法之后");
}
}
<?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 id="book" class="com.sitech.test11.Book"></bean>
<bean id="myBook" class="com.sitech.test11.MyBook"></bean>
<aop:config>
<aop:pointcut expression="execution(* com.sitech.test11.Book.look(..))" id="pointcut1"/>
<aop:aspect ref="myBook">
<aop:before method="before" pointcut-ref="pointcut1" />
<aop:after-returning method="after" pointcut-ref="pointcut1"/>
<aop:around method="around" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
</beans>
package com.sitech.test11;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test11 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test11.xml");
Book book = (Book) applicationContext.getBean("book");
book.look();
}
}
com.sitech.test11.MyBook.before()
方法之前
com.sitech.test11.Book.look()
方法之后
com.sitech.test11.MyBook.after()
四、aspectj的注解方式实现AOP
package com.sitech.test12;
import org.springframework.stereotype.Component;
@Component(value="book")
public class Book {
public void look() {
System.out.println(getClass().getName() + ".look()");
}
}
- 增强类:在类名上增加@Aspect注解表示开启AOP增强类
package com.sitech.test12;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component(value="myBook")
public class MyBook {
@Before(value="execution(* com.sitech.test12.Book.look(..))")
public void before() {
System.out.println(getClass().getName() + ".before()");
}
@AfterReturning(value="execution(* com.sitech.test12.Book.look(..))")
public void after() {
System.out.println(getClass().getName() + ".after()");
}
@Around(value="execution(* com.sitech.test12.Book.look(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("方法之前");
proceedingJoinPoint.proceed();
System.out.println("方法之后");
}
}
<?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:context="http://www.springframework.org/schema/context" 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">
<context:component-scan base-package="com.sitech.test12"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
package com.sitech.test12;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test12 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test12.xml");
Book book = (Book) applicationContext.getBean("book");
book.look();
}
}
- 运行结果:这里环绕通知会在前置通知之前执行,与XML配置结果不同
方法之前
com.sitech.test12.MyBook.before()
com.sitech.test12.Book.look()
方法之后
com.sitech.test12.MyBook.after()
五、基于代理的AOP实现
package com.sitech.test13;
public interface BaseBook {
void look();
}
package com.sitech.test13;
import org.springframework.stereotype.Component;
@Component(value="book")
public class Book
implements BaseBook {
public void look() {
System.out.println(getClass().getName() + ".look()");
}
}
package com.sitech.test13;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.*;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;
@Aspect
@Component(value="myBook")
public class MyBook
implements MethodBeforeAdvice, AfterReturningAdvice {
@Override
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println(getClass().getName() + ".before()");
}
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println(getClass().getName() + ".afterReturning()");
}
}
<?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:context="http://www.springframework.org/schema/context" 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">
<context:component-scan base-package="com.sitech.test13"></context:component-scan>
<bean id="lookPoincut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*look"></property>
</bean>
<bean id="bookAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="myBook"></property>
<property name="pointcut" ref="lookPoincut"></property>
</bean>
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="book"></property>
<property name="interceptorNames" value="bookAdvisor"></property>
<property name="proxyInterfaces" value="com.sitech.test13.BaseBook"></property>
</bean>
</beans>
package com.sitech.test13;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test13 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test13.xml");
BaseBook book = (BaseBook) applicationContext.getBean("proxy");
book.look();
}
}
com.sitech.test13.MyBook.before()
com.sitech.test13.Book.look()
com.sitech.test13.MyBook.afterReturning()