Spring Aop入门之Aspectj 进阶1

采用上一篇的注释虽然好,但是代码分散,也不容量看出彼此的关系,对于应用来说维护不方便。

以下采用自动组装方式

1.定义一个接口

package test.org.springframework.aop.aspectj.ycl.service;

/**
 * <p>接口[引入]</p>
 * @author chunlongy
 *
 */
public interface AService {

 public void fooA(String _msg);     
   
    public void barA();     
   
    public int get(int a);     
}

2.定义一个实现

package test.org.springframework.aop.aspectj.ycl.service;

/**
 * 接口A的实现
 * @author chunlongy
 *
 */
public class AServiceImpl implements AService {

 public void barA() {
  // TODO Auto-generated method stub
  System.out.println("AServiceImpl.barA()");     
 }

 public void fooA(String _msg) {
  // TODO Auto-generated method stub
  System.out.println("AServiceImpl.fooA(msg:"+_msg+")");     
 }
 
 public int get(int a){
  return a;
 }

}

3.定义另一个基本类

package test.org.springframework.aop.aspectj.ycl.service;

public class BServiceImpl {

  public void barB(String _msg, int _type) {     
         System.out.println("BServiceImpl.barB(msg:"+_msg+" type:"+_type+")");     
         if(_type == 1)     
             throw new IllegalArgumentException("测试异常个尼");     
     }     
     
     public void fooB() {     
         System.out.println("BServiceImpl.fooB()");     
     }     

}

4.定义一个切面

package test.org.springframework.aop.aspectj.ycl;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * <p>切面</p>
 * @author chunlongy
 *
 */
public class TestAspect {

  public void doAfter(JoinPoint jp) {     
         System.out.println("log Ending method: "    
                 + jp.getTarget().getClass().getName() + "."    
                 + jp.getSignature().getName());     
     }     
     
     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {     
         long time = System.currentTimeMillis();     
         Object retVal = pjp.proceed();  //这是主方法的执行   
         //i will be rewrite the method's result;
         time = System.currentTimeMillis() - time;
       
         System.out.println("ycl:process time: " + time + " ms");
         //int aa=Integer.parseInt(retVal.toString())+3;
         //这里重新设置返回值.
         return retVal;     
     }     
     
     public void doBefore(JoinPoint jp) {
         System.out.println("log Begining method: "    
                 + jp.getTarget().getClass().getName() + "."    
                 + jp.getSignature().getName());     
     }     
     
     public void doThrowing(JoinPoint jp, Throwable ex) {     
         System.out.println("method " + jp.getTarget().getClass().getName()     
                 + "." + jp.getSignature().getName() + " throw exception");     
         System.out.println(ex.getMessage());     
     }     
     
     private void sendEx(String ex) {     
         //TODO 发送短信或邮件提醒     
     }     
 
}

5.定义app.xml

<?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-2.0.xsd     
            http://www.springframework.org/schema/aop     
            http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"     
    default-autowire="autodetect">     
    <aop:config>     
        <aop:aspect id="TestAspect" ref="aspectBean">         
            <aop:pointcut id="businessService"    
                expression="execution(* test.org.springframework.aop.aspectj.ycl.service.*.*(..))" /> 
                <!-- 定义连接点 -->   
            <aop:before pointcut-ref="businessService" method="doBefore"/><!-- 定义前置通知 -->
            <aop:after pointcut-ref="businessService" method="doAfter"/> <!-- 定义后置通知  -->
            <aop:around pointcut-ref="businessService" method="doAround"/> <!--定义环绕通知   -->
            <aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>
            <!-- 定义异常通知 -->
        </aop:aspect>     
    </aop:config>     
         
    <bean id="aspectBean" class="test.org.springframework.aop.aspectj.ycl.TestAspect" /> 
    <!-- 切面 -->   
    <bean id="aService" class="test.org.springframework.aop.aspectj.ycl.service.AServiceImpl"></bean> 
    <!-- a类 -->   
    <bean id="bService" class="test.org.springframework.aop.aspectj.ycl.service.BServiceImpl"></bean>
    <!-- b类 -->     
    
</beans>   

6. 测试用例

package test.org.springframework.aop.aspectj.ycl;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import test.org.springframework.aop.aspectj.ycl.service.AService;
import test.org.springframework.aop.aspectj.ycl.service.BServiceImpl;

public class AOPTest {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  AOPTest test=new AOPTest();
  test.domy();
 }
 public void domy(){
  ApplicationContext context = new ClassPathXmlApplicationContext(
    "app.xml", this.getClass());
  //AService aservice=(AService)context.getBean("aService");
  //System.out.println("result"+aservice.get(1));
  //采用proxy
 
  BServiceImpl bservice=(BServiceImpl)context.getBean("bService");
  bservice.barB("ycl", 1);
  //采用cglib
 }

}

讲解:前置通知,后置通知是无论如何都是在方法前和方法后调用的,而环绕通知的执行方式是可以重写或跳过主程序的执行,或都用另一个方法代替主程序的执行,异常通知,则当发生异常时如果要记录日志等操作,则会拦截异常信息。

Spring的AOP解决了调用者和被调用者的耦合,但是却是基于方法的调用,比如我一个项目的Action调用Service的方法,那么我Action就必须调用相应的逻辑处理,当然这是必须的,然后返回相应的响应。

我指的只是一方面,我Action只调用逻辑是很简单的,在调用之前还要加一些请求参数等Validate,那么我完全可以把这些参数组装成对象,然后在调用逻辑方法之前进行拦截,如果不通过,则可以跳过逻辑的执行,正常完成跳转。在调用时可能会有一些Exception,那么我完全可以拦截Exception,并记录异常日志。在调用后可能需要关系数据的同步,那么可以执行目标同步方法。

当然AOP可以完成很多关联程序的执行,在不改变原程序代码的情况下进行相应的扩展,包括事务,日志等的控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值