天天看點

spring aop(面向切面) 詳解一,xml 方式:二, 注解的方式三,待處理問題:

spring aop(面向切面) 詳解一,xml 方式:二, 注解的方式三,待處理問題:

使用aop 的方式有兩種, 一種是 xml 方式, 另一種是 annotation 方式;

一,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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.2.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"
    default-autowire="default" default-lazy-init="false">

    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="spring"></context:component-scan>


    <bean id="xmlAopTest" class="spring.aop.xml.XmlAopTest"></bean>

    <aop:config>
        <aop:aspect ref="xmlAopTest">
            <aop:pointcut expression="execution(* spring.aop.target..*.*(..))" id="xmlAop"/>
            <aop:before pointcut-ref="xmlAop" method="beforeMethod" />
            <aop:after method="afterMethod" pointcut-ref="xmlAop"/>
            <aop:after-returning method="afterReturnMethod" pointcut-ref="xmlAop" returning="resultVal"/>
            <aop:after-throwing method="afterThrowingMethod" pointcut-ref="xmlAop" throwing="ex"/>
            <aop:around method="aroundMethod" pointcut-ref="xmlAop"/>
        </aop:aspect>
    </aop:config>
</beans>

           

通知的具體方式:

package spring.aop.xml;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * xml形式 aop 配置
 * @author wwp
 *
 */
public class XmlAopTest {

    private Logger log = Logger.getLogger(getClass());

    /**
     * 前置通知
     */
    public void beforeMethod(JoinPoint jp){
        System.out.println("這是前置通知");
    }

    /**
     * 後置通知
     */
    public void afterMethod(JoinPoint jp){
        System.out.println("這是一個後置通知");
    }

    /**
     * 傳回後通知
     */
    public void afterReturnMethod(JoinPoint jp, Object resultVal){
        log.info("這是傳回後通知, returning: " + resultVal);
    }

    /**
     * 異常抛出後通知
     */
    public void afterThrowingMethod(JoinPoint jp, Throwable ex){
        log.info("異常抛出後通知");
    }

    /**
     * 環繞通知
     * @throws Throwable 
     */
    public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
        log.info("環繞通知前");
        pjp.proceed();
        log.info("環繞通知後");
    }
}
           

測試類:

package spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import spring.aop.target.Target;

public class Test {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Target target = (Target) ac.getBean("target");
        target.sum(, );
    }
}
           

最後運作結果

-- ::, INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2bb57fd1: startup date [Fri Oct  :: CST ]; root of context hierarchy>
-- ::, INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [applicationContext.xml]>
-- ::, INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@b10b9b2: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,target,springTestDao,springTestService,xmlAopTest,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,org.springframework.aop.aspectj.AspectJPointcutAdvisor#2,org.springframework.aop.aspectj.AspectJPointcutAdvisor#3,org.springframework.aop.aspectj.AspectJPointcutAdvisor#4,xmlAop,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy>
-- ::, INFO [spring.dao.impl.SpringTestDao] - <SpringTestDao constructor !!!>
這是前置通知
-- ::, INFO [spring.aop.xml.XmlAopTest] - <環繞通知前>
-- ::, INFO [spring.aop.xml.XmlAopTest] - <異常抛出後通知>
這是一個後置通知
Exception in thread "main" java.lang.RuntimeException: aop運作時異常
    at spring.aop.target.Target.sum(Target.java:)
    at spring.aop.target.Target$$FastClassBySpringCGLIB$$d6d00021.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:)
    at spring.aop.xml.XmlAopTest.aroundMethod(XmlAopTest.java:)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
    at java.lang.reflect.Method.invoke(Method.java:)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:)
    at spring.aop.target.Target$$EnhancerBySpringCGLIB$$sum(<generated>)
    at spring.Test.main(Test.java:)
           

二, 注解的方式

配置檔案
           
<?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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.2.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"
    default-autowire="default" default-lazy-init="false">

    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="spring"></context:component-scan>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- 必須 -->

</beans>

           

注解aop

package spring.aop.annotation;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * aop使用注解方式
 * @author wwp
 *
 */
@Aspect
@Component
public class AnnotationAopTest {

    private Logger log = Logger.getLogger(getClass());

    /**
     * 定義切入點(有異常)
     */
    @Pointcut("execution(* spring.aop.target..*(..))")
    public void pointcut(){};

    /**
     * 前置通知
     */
    @Before("execution(* spring.aop.target..*(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置通知");
    }



}
           

測試方法同上,

測試結果:

-- ::, INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3348854d: startup date [Fri Oct  :: CST ]; root of context hierarchy>
-- ::, INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [applicationContext.xml]>
-- ::, INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@136fdd2d: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,annotationAopTest,target,springTestDao,springTestService,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy>
-- ::, INFO [spring.dao.impl.SpringTestDao] - <SpringTestDao constructor !!!>
前置通知
Exception in thread "main" java.lang.RuntimeException: aop運作時異常
    at spring.aop.target.Target.sum(Target.java:)
    at spring.aop.target.Target$$FastClassBySpringCGLIB$$d6d00021.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:)
    at spring.aop.target.Target$$EnhancerBySpringCGLIB$$caebf5.sum(<generated>)
    at spring.Test.main(Test.java:)
           

execution 表達式文法

表達式 含義
execution(public * *(..)) 任意方法
execution(* set*(..) set 開頭的任意方法
execution(* com.xyz.service.AccountService.*(..) 類AccountService 中的任意方法
execution(* com.xyz.service..(..)) 包 service 下的任意類的任意方法
execution(* com.xyz.service...(..)) service 包及其子包下的任意類的任意方法

三,待處理問題:

1,afterReturing 的具體使用
2,注解使用共用pointcut 報錯
3,如果需要在controller 層使用aop ,必須在 servlet 配置檔案中加上 <aop:aspectj-autoproxy/> <!-- 必須 -->