预编译方式:AspectJ
动态代理方式(JDK动态代理,CGLIB动态代理):Spring AOP,JbossAOP
2、基本概念切面(Aspect):对程序进行切割的类,描述切割的点和切割前后需要执行的动作。
连接点(Joinpoint):符合切入点条件的某个具体的点。
通知(Advice):对应切面中要执行的某个动作。
切入点(Pointcut):切面要切割程序的位置。
引入(Introduction):
目标对象(Target Object):被切割的对象
3、通知的类型前置通知(Before advice):在连接点之前执行的通知。前置通知不能阻止连接点的执行,除非抛出异常。
后置通知(After advice):在连接点之后执行的通知。
返回后通知(After returning advice):在连接点正常完成退出后执行的通知。
异常后通知(After throwing advice):在连接点抛出异常退出后执行的通知。
环绕通知(Around advice):包围连接点的通知,可以在连接点前后执行某些操作。
4、常用切入点表达式执行所有的public方法:
`execution(public * *(..))`
执行所有以set开始的方法:
`execution(* set*(..))`
执行HelloSpringService类中的所有方法:
`execution(* com.learn.service.HelloSpringService.*(..))`
执行service包中的所有方法:
`execution(* com.learn.service..(..))`
执行service包及子包下的所有方法:
`execution(* com.learn.service...(..))`
5、程序示例
xml文件中添加对aop的支持
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
声明切面,切面中添加切入点和通知
<bean id="myAspect" class="learn.service.MyAspect"></bean>
<bean id="helloService" class="learn.service.HelloServiceImpl"></bean>
<aop:config>
<aop:pointcut id="pointcut1" expression="execution(* learn.service.HelloServiceImpl.serviceSave(..))"/>
<aop:pointcut id="pointcut2" expression="execution(* learn.service.HelloServiceImpl.serviceSay(String))
and args(word)"/>
<aop:aspect id="aspectTest" ref="myAspect">
<!--前置通知-->
<aop:before method="beforeAdvice" pointcut-ref="pointcut1"></aop:before>
<!--返回后通知-->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut1"/>
<!--后置通知-->
<aop:after method="afterAdvice" pointcut-ref="pointcut1"/>
<!--异常后通知-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut1"/>
<!--无参环绕通知-->
<aop:around method="aroundAdvice" pointcut-ref="pointcut1"/>
<!--带参环绕通知-->
<aop:around method="aroundAdvice2" pointcut-ref="pointcut2"/>
</aop:aspect>
</aop:config>
切面类
public class MyAspect {
public void beforeAdvice()
{
System.out.println("beforeAdvice | before advice");
}
public void afterReturning()
{
System.out.println("afterReturning | after returning advice");
}
public void afterAdvice()
{
System.out.println("afterAdvice | after advice");
}
public void afterThrowing()
{
System.out.println("afterThrowing | after throwing advice");
}
public void aroundAdvice(ProceedingJoinPoint pdj) throws Throwable
{
System.out.println("aroundAdvice | 1 around advice");
pdj.proceed();
System.out.println("aroundAdvice | 2 around advice");
}
public void aroundAdvice2(ProceedingJoinPoint pdj, String word) throws Throwable
{
System.out.println("aroundAdvice2 | 1 around advice");
pdj.proceed();
System.out.println("aroundAdvice2 | 2 around advice");
}
}
6、Introductions
Introductions为匹配到的Bean类型增加一个父类接口,并在指定的类中增加该接口的实现细节。
xml配置
<aop:config>
<aop:pointcut id="pointcut1" expression="execution(* learn.service.HelloServiceImpl.serviceSave(..))"/>
<aop:aspect id="aspectTest" ref="myAspect">
<aop:declare-parents types-matching="learn.service.HelloServiceImpl"
implement-interface="learn.interfaces.Singer"
default-impl="learn.service.SingerImpl"/>
</aop:aspect>
</aop:config>
接口
package learn.interfaces;
public interface Singer {
void sing();
}
实现类
package learn.service;
import learn.interfaces.Singer;
public class SingerImpl implements Singer {
public void sing() {
System.out.println("sing a song!!");
}
}
验证程序
Singer helloService = (Singer) context.getBean("helloService");
helloService.sing();
输出
sing a song!!