聊聊AOP

对于aop的配置方式 我在网上搜了好多 自己整理了一下 (不对请指正 )

 
aop的两种配置方式 
第一种:通过定义aspectj切面类实现
第二种:通过通知器Advisor实现
这两种方式都能实现aop功能, 但是 advisor通常是实现Spring的声明式事务(我不知道怎么通过apectJ来实现aop事务!!)
aspectJ是实现aop开发的 (有些人把aop分为两种方式 一种是基于XML配置的AspectJ 一种是基于注解版的AspectJ 我不理解 我感觉Advisor通知器也应该算aop的一种实现方式)
aspectJ和Advisor的异同点:aspectJ把切面直接封装到了一个类中 而Advisor是通过组装拼接的方式形成的切面
aspectJ的通知是方法 但是 Advisor的通知是类 (通知类实现了相应的Method*Advice接口的实现)
 
 
废话不多说 直接代码演示吧!!!!! 
第一种是基于Advisor实现Spring的AOP配置
--(关于AspectJ的事务配置不太了解)
<!-- 事务控制器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>
 
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="pointPut" expression="execution(* com.xc.service.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointPut"/>
</aop:config>
 
 
<tx:method>属性值
#isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
#propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
#read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
#timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
#rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
#no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚
 
代码测试 测试Spring框架对事务的支持 
无AOP事务
 
数据库初始值
在未开启aop事务时执行转账操作
转账业务
程序报错 (除0错误) 查看数据库数据,无事务 ,数据出错
有AOP事务
还原数据库数据
 
放开AOP事务配置
 
执行程序,程序报错  查看数据库  (数据库数据没有发生变化 )
 

 
第二种基于Advisor实现AOP
# 第一步:需要注册通知类  通知类必须实现Method**Advice接口 我测试采用MethodBeforeAdvice接口
@Component
public class Before implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("哈哈哈哈");
    }
}
  
#第二步:在xml配置文件中组装AOP的通知器  (我用过自动扫描加载Before对象,不过没设置自动扫描 请用bean标签注册before类)
<!--基于advisor通知其实现AOP功能-->
<aop:config>
    <aop:pointcut id="pc1" expression="execution(* com.xc.service.impl.*.*(..))"/>
    <aop:advisor advice-ref="before" pointcut-ref="pc1"/>
</aop:config>
 
 

代码测试:
首先注释掉AOP配置信息
 
测试程序跑完 无AOP功能
 
放开AOP配置
 
 
测试显示  AOP功能实现(哈哈哈哈就是对功能增强   通过advisor配置也可以实现前置通知 后置通知 环绕通知   只不过需要多注册几个通知类 实现不同的接口)
 
 
 
 

 
3:基于AspectJ的AOP配置  
--除了环绕通知需要参数ProceedingJoinPoint pjp  别的通知可加可不加  JoinPoint是切入点  
1 第一步 需要配置切面类 AspectJ 
public class MyAspect {
    /**
     * 前置通知:目标方法调用之前执行的代码
     * @param jp
     */
    public void doBefore(JoinPoint jp){
        System.out.println("===========执行前置通知============");
    }
 
 
    /**
     * 后置返回通知:目标方法正常结束后执行的代码
     * 返回通知是可以访问到目标方法的返回值的
     * @param jp
     * @param result
     */
    public void doAfterReturning(JoinPoint jp,String result){
        System.out.println("===========执行后置通知============");
        System.out.println("返回值result==================="+result);
    }
 
 
    /**
     * 最终通知:目标方法调用之后执行的代码(无论目标方法是否出现异常均执行)
     * 因为方法可能会出现异常,所以不能返回方法的返回值
     * @param jp
     */
    public void doAfter(JoinPoint jp){
        System.out.println("===========执行最终通知============");
    }
 
 
    /**
     *
     * 异常通知:目标方法抛出异常时执行的代码
     * 可以访问到异常对象
     * @param jp
     * @param ex
     */
    public void doAfterThrowing(JoinPoint jp,Exception ex){
        System.out.println("===========执行异常通知============");
    }
 
 
    /**
     * 环绕通知:目标方法调用前后执行的代码,可以在方法调用前后完成自定义的行为。
     * 包围一个连接点(join point)的通知。它会在切入点方法执行前执行同时方法结束也会执行对应的部分。
     * 主要是调用proceed()方法来执行切入点方法,来作为环绕通知前后方法的分水岭。
     *
     * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
     * 而且环绕通知必须有返回值,返回值即为目标方法的返回值
     * @param pjp
     * @return
     * @throws Throwable
     */
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("======执行环绕通知开始=========");
        // 调用方法的参数
        Object[] args = pjp.getArgs();
        // 调用的方法名
        String method = pjp.getSignature().getName();
        // 获取目标对象
        Object target = pjp.getTarget();
        // 执行完方法的返回值
        // 调用proceed()方法,就会触发切入点方法执行
        Object result=pjp.proceed();
        System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result);
        System.out.println("======执行环绕通知结束=========");
        return result;
    }
}
 
第二步:在spring配置文件配置
<!--基于XML配置的AspectJ的AOP -->
<bean id="myAspect" class="com.xc.aspect.MyAspect"></bean>
<aop:config>
    <aop:aspect ref="myAspect">
        <aop:pointcut id="pointcut" expression="execution(* com.xc.service.impl.*.*(..))"/>
        <aop:before method="doBefore" pointcut-ref="pointcut"/>
        <aop:after-returning method="doAfterReturning" pointcut-ref="pointcut" returning="result"/>
        <aop:after method="doAfter" pointcut-ref="pointcut" />
        <aop:around method="doAround" pointcut-ref="pointcut"/>
        <aop:after-throwing method="doAfterThrowing" pointcut-ref="pointcut" throwing="ex"/>
    </aop:aspect>
</aop:config>
 
代码测试 
首先注释掉AOP的配置信息
 
测试显示  无AOP功能
 
放开AOP  
 
 
测试显示  AOP功能实现
 
 

第四种  AspectJ注解实现AOP
 
第一步:定义AnnotationAspectJ类 (通过注解配置)
@Aspect
public class AnnotationAspectJ {
 
 
    /**
     * 必须为final String类型的,注解里要使用的变量只能是静态常量类型的
     */
    public static final String EDP = "execution(* com.xc.service.impl.*.*(..))";
 
    /**
     * 切面的前置方法 即方法执行前拦截到的方法
     * 在目标方法执行之前的通知
     *
     * @param jp
     */
    @Before(EDP)
    public void doBefore(JoinPoint jp) {
 
 
        System.out.println("=========执行前置通知==========");
    }
 
 
 
 
    /**
     * 在方法正常执行通过之后执行的通知叫做返回通知
     * 可以返回到方法的返回值 在注解后加入returning
     *
     * @param jp
     * @param result
     */
    @AfterReturning(value = EDP, returning = "result")
    public void doAfterReturning(JoinPoint jp, String result) {
        System.out.println("===========执行后置通知============");
    }
 
 
    /**
     * 最终通知:目标方法调用之后执行的通知(无论目标方法是否出现异常均执行)
     *
     * @param jp
     */
    @After(value = EDP)
    public void doAfter(JoinPoint jp) {
        System.out.println("===========执行最终通知============");
    }
 
 
    /**
     * 环绕通知:目标方法调用前后执行的通知,可以在方法调用前后完成自定义的行为。
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around(EDP)
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
 
 
        System.out.println("======执行环绕通知开始=========");
        // 调用方法的参数
        Object[] args = pjp.getArgs();
        // 调用的方法名
        String method = pjp.getSignature().getName();
        // 获取目标对象
        Object target = pjp.getTarget();
        // 执行完方法的返回值
        // 调用proceed()方法,就会触发切入点方法执行
        Object result = pjp.proceed();
        System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result);
        System.out.println("======执行环绕通知结束=========");
        return result;
    }
 
 
    /**
     * 在目标方法非正常执行完成, 抛出异常的时候会走此方法
     *
     * @param jp
     * @param ex
     */
    @AfterThrowing(value = EDP, throwing = "ex")
    public void doAfterThrowing(JoinPoint jp, Exception ex) {
        System.out.println("===========执行异常通知============");
    }
}
 
 
第二步 :spring配置文件
<!--基于注解版的AspectJ 实现AOP-->
<!--开启spring对AspectJ的AOP注解支持 -->
<aop:aspectj-autoproxy/>
<!--注册Aspectj对象 -->
<bean class="com.xc.aspect.AnnotationAspectJ"/>
 
代码测试
干掉配置文件AOP配置
代码测试  无AOP功能
 
 
放开Spring配置 
 
测试代码   测试结果如下  
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值