spring aop(面向切面) 详解

来源:互联网 发布:淘宝如何清空收藏夹 编辑:程序博客网 时间:2024/06/05 19:29

这里写图片描述
使用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(3, 6);    }}

最后运行结果

2016-10-07 04:20:34,907 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2bb57fd1: startup date [Fri Oct 07 04:20:34 CST 2016]; root of context hierarchy>2016-10-07 04:20:34,982 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [applicationContext.xml]>2016-10-07 04:20:35,796 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>2016-10-07 04:20:36,126 INFO [spring.dao.impl.SpringTestDao] - <SpringTestDao constructor !!!>这是前置通知2016-10-07 04:20:36,156 INFO [spring.aop.xml.XmlAopTest] - <环绕通知前>2016-10-07 04:20:36,185 INFO [spring.aop.xml.XmlAopTest] - <异常抛出后通知>这是一个后置通知Exception in thread "main" java.lang.RuntimeException: aop运行时异常    at spring.aop.target.Target.sum(Target.java:11)    at spring.aop.target.Target$$FastClassBySpringCGLIB$$d6d00021.invoke(<generated>)    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:700)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)    at spring.aop.xml.XmlAopTest.aroundMethod(XmlAopTest.java:50)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    at java.lang.reflect.Method.invoke(Method.java:606)    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:51)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:42)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633)    at spring.aop.target.Target$$EnhancerBySpringCGLIB$$95845339.sum(<generated>)    at spring.Test.main(Test.java:12)

二, 注解的方式

配置文件
<?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@Componentpublic 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("前置通知");    }}

测试方法同上,
测试结果:

2016-10-07 05:00:49,877 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3348854d: startup date [Fri Oct 07 05:00:49 CST 2016]; root of context hierarchy>2016-10-07 05:00:49,952 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [applicationContext.xml]>2016-10-07 05:00:50,789 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>2016-10-07 05:00:51,074 INFO [spring.dao.impl.SpringTestDao] - <SpringTestDao constructor !!!>前置通知Exception in thread "main" java.lang.RuntimeException: aop运行时异常    at spring.aop.target.Target.sum(Target.java:11)    at spring.aop.target.Target$$FastClassBySpringCGLIB$$d6d00021.invoke(<generated>)    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:700)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633)    at spring.aop.target.Target$$EnhancerBySpringCGLIB$$2caebf5.sum(<generated>)    at spring.Test.main(Test.java:12)

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/> <!-- 必须 -->
0 0