aspectj

使用proxy指定劫持的class和需要的advise或者advisor
advise是用來指定需要插入的內容和位置
advisor傳入advise用來指定method
advise有四種形式
before: MethodBeforeAdvice 在方法調用前

public class HijackBeforeMethod implements MethodBeforeAdvice {

    public void before(Method arg0, Object[] args, Object target)
            throws Throwable {
        System.out.println("HijackBeforeMethod : Before method hijacked!");

    }

}

afterreturning:AfterReturningAdvice 在方法返回後

public class HijackAfterMethod implements AfterReturningAdvice {

    public void afterReturning(Object returnValue, Method method, Object[] args,
            Object target) throws Throwable {
        System.out.println("HijackAfterMethod : After method hijacked!");

    }

}

after-throwing:ThrowsAdvice 拋出異常時

public class HijackThrowExceptionMethod implements ThrowsAdvice {

    public void afterThrowing(IllegalArgumentException e) throws Throwable {
        System.out.println("HijackThrowException : Throw exception hijacked!");
    }

}

around:MethodInterceptor 可以在實現這個藉口的類裏面同時實現上面三個功能

public class HijackAroundMethod implements MethodInterceptor {

    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("Method name : "
                + methodInvocation.getMethod().getName());
        System.out.println("Method arguments : "
                + Arrays.toString(methodInvocation.getArguments()));

        // 相當於  MethodBeforeAdvice
        System.out.println("HijackAroundMethod : Before method hijacked!");

        try {
            // 調用原方法,即調用CustomerService中的方法
            Object result = methodInvocation.proceed();

            // 相當於 AfterReturningAdvice
            System.out.println("HijackAroundMethod : After method hijacked!");

            return result;

        } catch (IllegalArgumentException e) {
            // 相當於 ThrowsAdvice
            System.out.println("HijackAroundMethod : Throw exception hijacked!");
            throw e;
        }
    }

}

xml文檔

<bean id="hijackBeforeMethodBean" class="com.shiyanlou.spring.aop.advice.HijackBeforeMethod" />
   <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
           <!-指定需要劫持的class->
        <property name="target" ref="customerService" />
        <!--指定advise-->
        <property name="interceptorNames"> 
            <list>
                <value>hijackAroundMethodBean</value>
            </list>
        </property>
    </bean>

最後從context中獲得的bean是代理器而不是劫持的class本身


public class App {

    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                new String[] { "SpringAOPAdvice.xml" });

        CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxy");


        System.out.println("*************************");
        cust.printName();
        System.out.println("*************************");
        cust.printURL();
        System.out.println("*************************");

        try {
            cust.printThrowException();
        } catch (Exception e) {

        }

    }

}

註解實現aspectj

@Aspect
public class LoggingAspect {
    //*表示任意的返回類型,後面是指定的class和method。(..)指任意的參數,class和method可以用*來表示任意class或者method
  @Before("execution(public * com.shiyanlou.spring.aop.aspectj.CustomerBo.addCustomer(..))")
    public void logBefore(JoinPoint joinPoint){
        System.out.println("logBefore() is running ...");
        System.out.println("hijacked:"+joinPoint.getSignature().getName());
        System.out.println("**********");
    }

    @After("execution(public * com.shiyanlou.spring.aop.aspectj.CustomerBo.deleteCustomer(..))")
    public void logAfter(JoinPoint joinPoint){
        System.out.println("logAfter() is running ...");
        System.out.println("hijacked:"+joinPoint.getSignature().getName());
        System.out.println("**********");
    }
}

以上是同時實現了pointcut和advise




@Aspect
public class PointcutDefine {
    //指定了pointcut。方法 customerLog 是一個簽名,在 Advice 中可以用此簽名代替切入點表達式,所以不需要在方法體內編寫實際代碼,只起到助記功能
    @Pointcut("execution(* test.CustomerBo.*(..))")
    public void customerLog(){


    }
}



@Aspect
public class LoggingAspect {

    //通過簽名來找到pointcut然後寫advise
    @Before("test.PointcutDefine.customerLog()")
    public void logBefore(JoinPoint joinPoint){
        System.out.println("logBefore() is running ...");
        System.out.println("hijacked:"+joinPoint.getSignature().getName());
        System.out.println("**********");
    }


    @After("test.PointcutDefine.customerLog()")
    public void logAfter(JoinPoint joinPoint){
        System.out.println("logAfter() is running ...");
        System.out.println("hijacked:"+joinPoint.getSignature().getName());
        System.out.println("**********");
    }
}

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:util="http://www.springframework.org/schema/util"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd">

   <aop:aspectj-autoproxy/>


    <bean id="customerBo" class="test.CustomerBo"/>
    <bean id="loggingAspect" class="test.LoggingAspect"/>
    <beans>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章