spring aop(面向切面) 详解
2016-10-07 03:10
316 查看
使用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(ReflectiveMeth 10a97 odInvocation.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 @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("前置通知"); } }
测试方法同上,
测试结果:
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/> <!-- 必须 -->
相关文章推荐
- Python的装饰器模式与面向切面编程详解
- SpringAOP面向切面详解(带实例)
- Spring AOP 面向切面编程
- spring aop 面向切面编程 如何来做一个强大的日志记录功能.原创
- aop面向切面详解
- Spring详解之二:AOP(面向切面)
- Spring AOP(面向切面)
- 详解spring面向切面aop拦截器
- JavaScript实现AOP详解(面向切面编程,装饰者模式)
- spring aop面向切面详解,以及heibernate和mybatis的区别(缓存)
- Spring3.0 学习-AOP面向切面编程_Spring AOP的注解模式即Aspectj模式
- Spring AOP(面向切面)实例及步骤
- SPRING AOP 面向切面编程 基本配置和注解配置 火推
- Spring3.0 学习-AOP面向切面编程_Spring AOP的XML配置模式
- Spring核心机制(面向切面编程AOP)详解
- Spring AOP 面向切面编程
- Spring AOP基于配置文件的面向方法的切面
- Spring AOP之AspectJ(面向切面编程) 案例详解
- Spring AOP 面向切面编程--实例
- 架构师之路(2)---详解面向过程