1. 程式人生 > >Spring-註解的方式配置AOP-案例

Spring-註解的方式配置AOP-案例

需求:分別在AtithmeticCalculator.java實現了該介面的類的加減乘除的方法執行時列印方法執行情況,並在方法執行前判斷所有引數是否都是int,用aop實現。

介面實現類:AtithmeticCalculatorImpl.java

/*
 * 檔名:AtithmeticCalculatorImpl.java
 * 版權:Copyright by www.huawei.com
 * 描述:
 * 修改人:Cuigaochong
 * 修改時間:2015-11-2
 * 跟蹤單號:
 * 修改單號:
 * 修改內容:
 */

package com.cgc.spring.aop.impl;

import org.springframework.stereotype.Component;

/**
 * <一句話功能簡述> <功能詳細描述>
 * 
 * @author 姓名 工號
 * @version [版本號, 2015-11-2]
 * @see [相關類/方法]
 * @since [產品/模組版本]
 */
@Component
public class AtithmeticCalculatorImpl implements AtithmeticCalculator
{
    
    /**
     * 過載方法
     * 
     * @param i
     * @param j
     * @return
     */
    @Override
    public int add(int i, int j)
    {
        int result = i + j;
        return result;
    }
    
    /**
     * 過載方法
     * 
     * @param i
     * @param j
     * @return
     */
    @Override
    public int sub(int i, int j)
    {
        int result = i - j;
        return result;
    }
    
    /**
     * 過載方法
     * 
     * @param i
     * @param j
     * @return
     */
    @Override
    public int mul(int i, int j)
    {
        int result = i * j;
        return result;
    }
    
    /**
     * 過載方法
     * 
     * @param i
     * @param j
     * @return
     */
    @Override
    public int div(int i, int j)
    {
        int result = 0;
        try
        {
            //前置通知
            result = i / j;
            //返回通知
        }
        catch (Exception e)
        {
            e.printStackTrace();
            //異常通知,可以訪問到出現的異常
        }
        
        //後置通知,因為方法可能會出現異常,所以訪問不到方法的返回值
        
        return result;
    }
    
}
第一個切面類:VlidationAspect.java實現判斷請求的引數是不是int
/*
 * 檔名:VlidationAspect.java
 * 版權:Copyright by www.huawei.com
 * 描述:
 * 修改人:Cuigaochong
 * 修改時間:2015-11-2
 * 跟蹤單號:
 * 修改單號:
 * 修改內容:
 */

package com.cgc.spring.aop.impl;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * <一句話功能簡述>
 * <功能詳細描述>
 * 
 * @author  姓名 工號
 * @version  [版本號, 2015-11-2]
 * @see  [相關類/方法]
 * @since  [產品/模組版本]
 */
//@Order(1)設定切面的優先順序  值越小  優先順序越高
@Order(1)
@Aspect
@Component
public class VlidationAspect
{
    //不同的包下要加包名   com.cgc.spring.aop.impl.LoggingAspect.declareJointPointExpression()
    @Before("LoggingAspect.declareJointPointExpression()")
    public void validateArrgs(JoinPoint joinPoint)
    {
        System.out.println("-->validate"+Arrays.asList(joinPoint.getArgs()));
        //可以在此處實現請求的引數是不是int型別,從joinPoint中可以獲取請求的引數
    }
}
第二個切面類:在不同方法執行前,列印不同方法的執行日誌:LoggingAspect.java
/*
 * 檔名:LoggingAspect.java
 * 版權:Copyright by www.huawei.com
 * 描述:
 * 修改人:Cuigaochong
 * 修改時間:2015-11-2
 * 跟蹤單號:
 * 修改單號:
 * 修改內容:
 */

package com.cgc.spring.aop.impl;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * <一句話功能簡述>
 * <功能詳細描述>
 * 
 * @author  姓名 工號
 * @version  [版本號, 2015-11-2]
 * @see  [相關類/方法]
 * @since  [產品/模組版本]
 */
//把一個類宣告為一個切面:需要把該類放入到IOC容器中,再宣告為一個切面
@Order(2)
@Aspect
@Component
public class LoggingAspect
{
    //定義一個方法,用於宣告切入點表示式,一般的  該方法中不需要再新增其他程式碼
    @Pointcut("execution(public int com.cgc.spring.aop.impl.AtithmeticCalculatorImpl.*(..) )")
    public void declareJointPointExpression()
    {
    }
    
    
    
    //宣告該方法是一個前置通知,在目標方法開始之前執行.第一個*表示任意修飾符  任意返回值,後邊的*表示任意方法名
    //@Before("execution(* com.cgc.spring.aop.impl.AtithmeticCalculatorImpl.*(int, int) )")
    @Before("declareJointPointExpression()")
    public void beforeMethod(JoinPoint joinPoint)
    {
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("this is method "+methodName +" begin with "+ args);
    }
    
    //後置通知:在目標方法執行後(無論是否發生異常),執行的通知
    //在後置通知中不能訪問在目標方法中返回的執行結果
    @After("execution(public int com.cgc.spring.aop.impl.AtithmeticCalculatorImpl.*(int, int) )")
    public void afterMethod(JoinPoint joinPoint)
    {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("this is method "+methodName +" end with ");
    }
    
    //在方法正常結束後要執行的程式碼
    //返回通知是可以訪問到方法的返回值的
    @AfterReturning(value="declareJointPointExpression()",returning="result")
    public void afterReturning(JoinPoint joinPoint,Object result)
    {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("this is method "+methodName +" after Returning " + result);
    }
    
    //在方法出現異常時,會執行的程式碼,而且可以訪問到異常物件,且可以指定在出現  特定異常時在執行通知程式碼 Exception ex,NullPointerException ex
    @AfterThrowing(value="declareJointPointExpression())",throwing="ex")
    public void afterThrowing(JoinPoint joinPoint , Exception ex)
    {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("this is method "+methodName +" after Returning exception " + ex);
    }
}
配置檔案:applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	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-4.0.xsd">
	
	<!-- 配置自動掃描的包 -->	
	<context:component-scan base-package="com.cgc.spring.aop.impl"></context:component-scan>
	
	<!-- 使Aspject 註解其作用:自動為匹配的類生成代理物件 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
			
</beans>
通過main呼叫方法:
 public static void main(String[] args)
    {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        AtithmeticCalculator cal = ac.getBean(AtithmeticCalculator.class);
        System.out.println(cal.getClass().getName());
        int result = cal.add(3, 4);
        System.out.println(result);
        int result00 = cal.div(10, 2);
        System.out.println(result00);
    }