4.1:面向切面编程
AOP是在运行期间将代码切入到类的指定位置的编程思想。切面能帮助我们模块化横切关注点,实现横切关注点的复用。Spring在运行期间将切面植入到指定的Bean中,实际是通过拦截方法调用的过程中插入了切面。
4.2:描述切点
SpringAOP中切点的定义使用了AspectJ的切点表达式。但是只支持AspectJ的部分切点表达式。arg(),@arg(),this(),target(),@target(),within()$within(),@annotation和execution()。这些切点指示器中execution()是用来实现执行匹配的,其他指示器用来限定匹配的切点。
切点案例:
execution(* 包.包.类.方法(..))
execution(* 包.包.类.方法(..) && within (包A.*)) //附加条件是:包A下的任何方法被调用
execution(* 包.包.类.方法(..) && bean("beanID")) //附加条件是:匹配特定的bean
execution(* 包.包.类.方法(..) && !bean("beanID")) //附加条件是:不匹配特定的bean
execution(* 包.包.类.方法(int) && args(property)) //有参数的切点
4.3:使用注解创建切面
使用注解创建切面需要启用AspectJ的自动代理,然后使用@After、@AfterReturning、@AfterThrowing、@Around、@Before注解配合java类创建切面。
启动AspectJ自动代理:
在java配置类中启动:
@Configuration
@EnableAspectJAutoProxy //启动AspectJ自动代理
@ComponentScan
public class ConcertConfig(){@Bean...}
在xml中启动:
<beans>
<aop:aspectJ-autoproxy> //启动AspectJ自动代理
</beans>
使用注解创建切面
package xxx;
/**
切点=切面+通知
*/
@Aspect
public class Audience{
//切点
@PointCut("execution(* 包.包.类.方法(..))")
public void performance(){} //用于承载切点,方法体不重要,之后使用方法名可调用切面。
//通知
@Before("performance()")
public void helloBefore(){System.out.println("前置通知执行")}
@AfterReturning("performance()")
public void helloAfterReturning(){System.out.println("返回后置通知执行")
@AfterThrowing("performance()")
public void helloAfterThrowing(){System.out.println("异常后置通知执行")}
}
使用注解创建环绕通知
package xxx;
@Aspect
public class Audience{
//切点
@PointCut("execution(* 包.包.类.方法(..))")
public void performance(){} //用于承载切点,方法体不重要,之后使用方法名可调用切面。
//环绕通知
@Around("performance()")
public void helloAround(ProceedingJoinPoint jp){
try{
//执行前置通知
jp.proceed();
//执行后置通知
}catch(Throwable e){
//调用异常通知
}
}
}
4.4:在xml中声明切面
一般切面
<aop:config>
<aop:aspect ref = "audience"> //ref 引用了ID为audience的Bean,这个bean中定义了通知方法。
<!--切点-->
<aop:pointcut id = "performance" expression = "execution(* 包.包.类.方法(..))" />
<!--环绕通知-->
<aop:before pointcut-ref = "performance" method = "通知A" />
<aop:after-returning pointcut-ref = "performance" method = "通知B" />
<aop:after-throwing> pointcut-ref = "performance" method = "通知C'/>
</aop:aspect>
</aop:config>
环绕通知切面
<aop:config>
<aop:aspect ref = "audience">
<!--切点-->
<aop:pointcut id = "performance" expression = "execution(* 包.包.类.方法(..))" />
<!--环绕通知-->
<aop:around pointcut-ref = "performance" method = "helloAround"> //指点环绕通知方法
</aop:aspect>
</aop:config>
4.5:注入AspectJ切面
???????????????????