如何用注解配置aop,如何通过自定义注解实现AOP切点定义

1,如何通过自定义注解实现AOP切点定义判断当前名为signatureName的方法是否在invokeClass类所实现的API接口中被Tag 。(实现3和4的判断)判断当前类是否为Object.class,若不是则执行第三步,否则执行第四步判断当前名为signatureName的方法是否在类invokeClass中被tag(实现1和2的判断)上面三项没有为真,则调用当前类的父类继续递归(实现5和6的判断)虽然我很聪明 , 但这么说真的难到我了
2 , 怎么动态配置aop开关AOP配置,@EnableAspectJAutoProxy,@Before , @After,@AfterReturning,@AfterThrowingAOP:【动态代理】指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;1.导入aop模块;Spring AOP:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>2.定义一个业务逻辑类(CalculateController);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常 , xxx)3.定义一个日志切面类(LogAop):切面类里面的方法需要动态感知CalculateController.calculateNum运行到哪里然后执行;通知方法:前置通知(@Before):logStart:在目标方法(calculateNum)运行之前运行后置通知(@After):logEnd:在目标方法(calculateNum)运行结束之后运行(无论方法正常结束还是异常结束)返回通知(@AfterReturning):logReturn:在目标方法(calculateNum)正常返回之后运行异常通知(@AfterThrowing):logException:在目标方法(calculateNum)出现异常以后运行环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())4.给切面类的目标方法标注何时何地运行(通知注解);5.将切面类和业务逻辑类(目标方法所在类)都加入到容器中;6.必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)7.给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】在Spring中很多的 @EnableXXX;三步:1)将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)2)在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)3)开启基于注解的aop模式;@EnableAspectJAutoProxy配置// @EnableAspectJAutoProxy 开启基于注解的aop模式@EnableAspectJAutoProxy@Configurationpublic class MyAopConfig@Beanpublic CalculateController calculateController()return new CalculateController();}@Beanpublic LogAop logAop()return new LogAop();}}/** * 切面类 */// @Aspect: 告诉Spring当前类是一个切面类@Aspectpublic class LogAop//抽取公共的切入点表达式//1、本类引用//2、其他的切面引用@Pointcut("execution(public int com.example.studywork.work.controller.CalculateController.*(..))")public void pointCut()@Before(value ="http://www.lisdn.com/mnsj/hhzs/pointCut()")public void logStart(JoinPoint joinPoint)System.out.println(joinPoint.getSignature().getName()+"方法运行前 。。。参数列表是:}// 外部切面类引用可以用全类名@After("com.example.studywork.work.aop.LogAop.pointCut()")public void logEnd(JoinPoint joinPoint)System.out.println(joinPoint.getSignature().getName()+"方法结束 。。。");}//JoinPoint一定要出现在参数表的第一位@AfterReturning(value = "http://www.lisdn.com/mnsj/hhzs/pointCut()",returning = "obj")public void logReturn(JoinPoint joinPoint,Object obj)System.out.println(joinPoint.getSignature().getName()+"方法正常返回 。。。运行结果是:}@AfterThrowing(value = "http://www.lisdn.com/mnsj/hhzs/pointCut()",throwing = "e")public void logxception(JoinPoint joinPoint,Exception e)System.out.println(joinPoint.getSignature().getName()+"方法异常返回 。。。异常结果是:}}// 业务public class CalculateControllerpublic int calculateNum(int i, int j)System.out.println("CalculateController类的calculateNum方法正在运行");return i/j;}}输出@Testpublic void test()AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyAopConfig.class);CalculateController bean = applicationContext.getBean(CalculateController.class);bean.calculateNum(1,1);}输出结果异常输出@Testpublic void test()AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyAopConfig.class);CalculateController bean = applicationContext.getBean(CalculateController.class);bean.calculateNum(1,0);}输出结果
3,spring 用注解实现aop 如何获取目标对象在方法参数加一个JoinPoint例如public void doBefore(JoinPoint jp)Object o =jp.getTarget();`//这个方法可以拿到目标对象}在spring中实现aop根据版本不同,可以有大致四种配置方式 。现简单列一下 。在介绍spring的aop配置方式前,先要注意spring中advisor的概念 。在spring中advisor是advice和pointcut的结合,但它还不是aop概念上的aspect 。【如何用注解配置aop,如何通过自定义注解实现AOP切点定义】
4,如何在sping31 MVC中应用aspect注解之AOP最近在项目有一个操作时间监控功能项目采用的是 spring3.1 mvc -control注解为了对所有的操作进行执行时间监控,编写了一个AOP配置mvc aop的时候,刚开始按照普通的aspect注解的方式配置 , 无法生效 。后面查了相关的资料,有的说@control不支持AOP ,有的说支持,但笔者最后还是成功的找到了相关的配置方法,因为笔者喜欢Aspect的注解风格 。所以笔者只提供Aspect风格的相关配置 。相关jar网上搜下 。笔者只讲mvc 切面生效的配置 。前提条件MVC配置成功 。编写AOP类[java] view plaincopypackage com.wx.aop.timer;import org.apache.log4j.Logger;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;@Component@Aspectpublic class TimerprivateLogger logger =Logger.getLogger(getClass());//可以尝试下这两种注解//@Around("execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))")@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")public Object logTimer(ProceedingJoinPoint thisJoinPoint) throws ThrowableString clazzName = thisJoinPoint.getTarget().getClass().getName();String methodName = thisJoinPoint.getSignature().getName();// 计时并调用目标函数long start = System.currentTimeMillis();Object result = thisJoinPoint.proceed();long time = System.currentTimeMillis() - start;// 输出计时信息logger.info("操作计时:" + time + "ms类名: " + clazzName+ "方法名:" + methodName + "()");return result;}}spring-servlet配置文件加入下面配置语句: <aop:aspectj-autoproxy proxy-target-class="true" /><!-- aspect注解生效--><!-- aop切面 --> <bean id="timer" class="com.wx.aop.timer.Timer" /> 笔者mvc配置文件为spring-servlet.xml.整个配置文件如下:[html] view plaincopy<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.1.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.1.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"><aop:aspectj-autoproxy proxy-target-class="true" /><!-- aspect注解生效--><!--servlet 配置,还需要注册dispathservlet 类 在web.xml中 。具体详情搜索相关的资料 网上很多 --><context:component-scan base-package="com.wx.servlet" /><bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/><bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/><!-- Default ViewResolver --><bean id="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="viewClass" value="http://www.lisdn.com/mnsj/hhzs/org.springframework.web.servlet.view.JstlView" /><property name="prefix" value="http://www.lisdn.com/WEB-INF/jsp/" /><property name="suffix" value="http://www.lisdn.com/mnsj/hhzs/.jsp"></property></bean><!-- aop切面 --><bean id="timer" class="com.wx.aop.timer.Timer" /></beans>5 , spring 中的AOP是怎么实现的1使用ProxyFactoryBean的代理2隐式使用ProxyFactoryBean的aop代理DefaultAdvisorAutoProxyCreator实现了BeanPostProcessor,它将自动检查advisor的pointcut是否匹配bean的方法,如果匹配会替换bean为一个proxy,并且应用其advice 。3使用注解的aop代理xml中增加了一个<aop:aspectj-autoproxy />,它创建了AnnotationAwareAspectJAutoProxyCreator在spring中,这个类将自动代理匹配的类的放方法 。和上个例子中DefaultAdvisorAutoProxyCreator做同样的工作 。4使用aop配置文件的自动代理采用这种方法,不用加<aop:aspectj-autoproxy />6,spring配置aop的方式有哪些在Spring中实现AOP根据版本不同,可以有大致四种配置方式 。现简单列一下 。在介绍Spring的AOP配置方式前 , 先要注意Spring中Advisor的概念 。在Spring中Advisor是Advice和Pointcut的结合 , 但它还不是AOP概念上的Aspect 。因为在Spring中Advisor还是Spring用来生成Aspect对象的一个原型,根据配置的不同,Spring可以只对某个类生成Aspect,也可以对所有的类生成Aspect 。1. 基于xml配置文件的代理配置方式这种方式在2.0以后很少用了,原因是配置项过多,过于繁琐 。但对于理解Spring AOP还是很有帮助的1.1 定义通知1.2 定义切点要定义一个切点,可以选择使用正则表达式方式声明的切点或者AspectJ方式声明的切点 。对正则表达式切点,使用Perl5RegexpMethodPointcut或JdkRegexpMethodPointcut(Java 1.4以上版本,不需要Jakarta ORO的支持了);对AspectJ切点,使用AspectJExpressPointcut1.3 定义通知者DefaultPointcutAdvisor是Spring提供的默认通知者,它需要提供通知和切点的引用 。Spring也提供了RegexpMethodPointcutAdvisor和AspectJExpressionPointcutAdvisor来对应两种声明切点的方式,不用再单独定义切点 。1.4 定义ProxyFactoryBeaninterceptorNames和proxyInterfaces都是数组属性,所以可以声明要使用的一个list,也可以让Spring自动把单个值转化为数组上面明确定义了要对那个targetBean应用代理生成切面实例 。如果不想限制targetBean,可以让Spring为所有匹配切点声明的bean生成切面实例 , 这样就不用一个个定义ProxyFactoryBean了,只需要定义这是一个BeanPostProcessor , 所以Spring会自动识别并在bean的声明周期使用2 利用2.0以后使用aop标签3 利用Annotation3.1 利用@Aspect将一个POJO类声明为一个切面 。3.2 定义切点@Pointcut("execution(* *.perform(..))")public void performance()通过@Pointcut定义的切点的名字就是它所注解的方法的名字,因此例子中的切点名字是performance() 。这里声明的performance()方法实际圣只是一个标记 , 为@Pointcut提供附加的点,并不要求有实际意义 。3.3 定义通知对要执行切面的方法,通过@Before("performance()"),@AfterReturning("performance()")来定义通知 。注意这里提供的切点名称,是performance(),而不是performance如果对上面的两点不是很理解,也可以省略@Pointcut,而将AspectJ表达式直接定义在@Before等通知中,将上面的两步合为一步,如@Before("execution(* *.perform(..))")3.4 通知Spring创建代理这实际上相当于声明了一个AnnotationAwareAspectJAutoProxyCreator,从而根据@Pointcut声明的切点来自动代理匹配的bean实例 4 在Spring中结合进AspectJ 对于超出Spring AOP支持范围的,可以采用这种方式 。只需要在Spring中配置AspectJ的Class实例时让Spring能够获得AspectJ类的实例就可以了,比如1. 基于xml配置文件的代理配置方式这种方式在2.0以后很少用了 , 原因是配置项过多,过于繁琐 。但对于理解spring aop还是很有帮助的1.1 定义通知1.2 定义切点要定义一个切点,可以选择使用正则表达式方式声明的切点或者aspectj方式声明的切点 。对正则表达式切点,使用perl5regexpmethodpointcut或jdkregexpmethodpointcut(java 1.4以上版本,不需要jakarta oro的支持了);对aspectj切点,使用aspectjexpresspointcut1.3 定义通知者defaultpointcutadvisor是spring提供的默认通知者 , 它需要提供通知和切点的引用 。spring也提供了regexpmethodpointcutadvisor和aspectjexpressionpointcutadvisor来对应两种声明切点的方式,不用再单独定义切点 。1.4 定义proxyfactorybeaninterceptornames和proxyinterfaces都是数组属性 , 所以可以声明要使用的一个list,也可以让spring自动把单个值转化为数组上面明确定义了要对那个targetbean应用代理生成切面实例 。如果不想限制targetbean,可以让spring为所有匹配切点声明的bean生成切面实例 , 这样就不用一个个定义proxyfactorybean了,只需要定义这是一个beanpostprocessor,所以spring会自动识别并在bean的声明周期使用2 利用2.0以后使用aop标签3 利用annotation3.1 利用@aspect将一个pojo类声明为一个切面 。3.2 定义切点@pointcut("execution(* *.perform(..))")public void performance()通过@pointcut定义的切点的名字就是它所注解的方法的名字,因此例子中的切点名字是performance() 。这里声明的performance()方法实际圣只是一个标记,为@pointcut提供附加的点 , 并不要求有实际意义 。3.3 定义通知对要执行切面的方法,通过@before("performance()"),@afterreturning("performance()")来定义通知 。注意这里提供的切点名称,是performance(),而不是performance如果对上面的两点不是很理解 , 也可以省略@pointcut,而将aspectj表达式直接定义在@before等通知中,将上面的两步合为一步 , 如@before("execution(* *.perform(..))")3.4 通知spring创建代理这实际上相当于声明了一个annotationawareaspectjautoproxycreator,从而根据@pointcut声明的切点来自动代理匹配的bean实例 4 在spring中结合进aspectj 对于超出spring aop支持范围的,可以采用这种方式 。只需要在spring中配置aspectj的class实例时让spring能够获得aspectj类的实例就可以了,比如

    推荐阅读