面向切面编程(AOP)
1、什么是面向切面编程
是一种通过预编译和运行期动态处理的方式实现在不修改源代码情况下程序动态添加功能的技术
AOP相关术语
1)增强处理
前置增强
后置增强
环绕增强、异常抛出增强、最终增强等类型
2)切入点(Pointcut)
3)连接点(Join Point)
4)切面(Aspect)
5)目标对象(Target object)
6)AOP代理(AOP proxy)
7)织入(Weaving)
2、基于jdk动态代理的经典AOP
需要导入的jar包
目标类
public class BookeServiceImpl implements BookService{
public double buy(String name) {
double money=80;
System.out.println("目标对象,买了一本书:"+name+"花费了"+money+"元");
return money;
}
}
代理类:
public class BookAdvice01 implements MethodBeforeAdvice, AfterReturningAdvice , ThrowsAdvice , MethodInterceptor {
public void before(Method method, Object[] args, Object target) throws Throwable {
//前置通知
System.out.println("购书之前,发送优惠券");
}
public void afterReturning(Object retVal, Method method, Object[] objects, Object o1) throws Throwable {
//后置通知
System.out.println("购书之后,返利");
if(retVal!=null){
double money=((Double)retVal).doubleValue();
if(money>100){
System.out.println("返利10元");
}else{
System.out.println("返利5元");
}
}
}
public void afterThrowing(Method method, Object[] objects, Object target,Exception ex){
//异常通知
System.out.println(ex.getMessage());
System.out.println("异常通知");
}
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("环绕通知开始");
Object retVal=methodInvocation.proceed();
System.out.println("环绕通知结束");
return retVal;
}
}
ApplicationContext.xml配置
<!-将目标对象放入容器-->
bean id="bookService" class="cn.smbms.bean.BookeServiceImpl"></bean>
<!--将目通知类放入容器-->
<bean id="bookAdvice01" class="cn.smbms.aop.BookAdvice01"></bean>
<aop:config>
<aop:pointcut id="serviceMethod" expression="execution(* cn.smbms.bean.BookeSrviceImpl.buy(..))"></aop:pointcut>
<!--引用通知-->
<aop:advisor advice-ref="bookAdvice01" id="bookAdvice" pointcut-ref="serviceMethod"></aop:advisor>-->
</aop:config>
3、纯POJO的AOP代理
目标类(同上)
代理类
public class BookAdvice02{
public void before(JoinPoint joinPoint){
//前置通知
System.out.println("购书之前,发送优惠券02");
System.out.println("买书"+joinPoint.getArgs()[0]);
}
public void afterReturning(Object retVal) {
//后置通知
System.out.println("购书之后,返利02");
if(retVal!=null){
double money=((Double)retVal).doubleValue();
if(money>100){
System.out.println("返利10元");
}else{
System.out.println("返利5元");
}
}
}
ApplicationContext.xml配置
<aop:config>
<aop:pointcut id="serviceMethod" expression="execution(* cn.smbms.bean.BookeSrviceImpl.buy(..))"></aop:pointcut>
<aop:aspect ref="bookAdvice02">
<!--method方法名称 returning是返回值名称-->
<aop:before method="before" pointcut-ref="serviceMethod"/>
<aop:after-returning method="afterReturning" pointcut-ref="serviceMethod" returning="retVal"></aop:after-returning>
</aop:aspect>
</aop:config>
4、基于注解AOP代理
目标类
@Component(value = "bookService")
public class BookeServiceImpl implements BookService{
@Override
public double buy(String name) {
double money=80;
System.out.println("目标对象,买了一本书:"+name+"花费了"+money+"元");
return money;
}
}
代理类
//基于注解的AOP代理
@Component
@Aspect
public class BookAdvice03 {
@Before(value = "execution(* cn.smbms.bean.BookeServiceImpl.buy(..))")
public void before(JoinPoint joinPoint){
//前置通知
System.out.println("购书之前,发送优惠券03");
System.out.println("买书"+joinPoint.getArgs()[0]);
}
@AfterReturning(value = "execution(* cn.smbms.bean.BookeServiceImpl.buy(..))",returning = "retVal")
public void afterReturning(Object retVal) {
//后置通知
System.out.println("购书之后,返利03");
if(retVal!=null){
double money=((Double)retVal).doubleValue();
if(money>100){
System.out.println("返利10元");
}else{
System.out.println("返利5元");
}
}
}
}
ApplicationContext.xml配置
<!--开启注解-->
<context:component-scan base-package="cn.smbms"/>
<aop:aspectj-autoproxy/>