基于注解的Spring AOP的配置和使用
Spring的AOP配置
Spring的AOP配置(2011-04-01 20:38:58)转载标签:分类:SSH框架springaop配置获取参数it1.先写一个普通类:package com.spring.aop;public class Common {public void execute(String username,String password){ System.out.println("------------------普通类----------------");}}2.写一个切面类,用于合法性校验和日志添加:package com.spring.aop;public class Check {public void checkValidity(){System.out.println("------------------验证合法性----------------"); }public void addLog(JoinPoint j){System.out.println("------------------添加日志----------------");Object obj[] = j.getArgs();for(Object o :obj){System.out.println(o);}System.out.println("========checkSecurity=="+j.getSignature().getName());//这个是获得方法名}}3.配置AOP,使用XML方式:(注意红色标志的内容)<?xml version="1.0" encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="common" class="mon"/><bean id="check" class="com.spring.aop.Check"/><aop:config><aop:aspect id="myAop" ref="check"><aop:pointcut id="target" expression="execution(*mon.execute(..))"/><aop:before method="checkValidity" pointcut-ref="target"/><aop:after method="addLog" pointcut-ref="target"/></aop:aspect></aop:config>注意:execution(* com.spring.aop.*.*(..))"/这样写应该就可以了这是com.aptech.jb.epet.dao.hibimpl 包下所有的类的所有方法。
基于SpringBootAOP与自定义注解转义字典值
基于SpringBootAOP与自定义注解转义字典值要基于SpringBoot、AOP和自定义注解来转义字典值,可以按照以下步骤进行:1.创建一个字典表,存储字典值和对应的转义值。
例如,可以创建一个数据库表或者在配置文件中定义一个字典映射关系。
4.在切面方法中,获取需要转义的字段的值,然后根据字典表中的映射关系,找到对应的转义值,并将转义值设置回字段。
5.在需要使用转义值的地方,直接使用被转义后的字段值即可。
下面是一个简单的示例代码:1.创建字典表,例如在配置文件中定义:```yamldict.mapping:gender:0:男1:女``````javaString value( default "";```3.创建AOP切面类:```javapublic class DictTransAspectprivate DictMapping dictMapping;public Object dictTrans(ProceedingJoinPoint joinPoint) throws ThrowableObject result = joinPoint.proceed(;//获取被标记的字段或方法Field field =ReflectionUtils.findField(joinPoint.getTarget(.getClass(, ((MethodSignature) joinPoint.getSignature().getName();DictTrans dictTrans = field.getAnnotation(DictTrans.class);if (dictTrans != null)//获取字段值Object value = field.get(joinPoint.getTarget();//获取字段的字典映射关系Map<String, String> mapping =dictMapping.getMapping(dictTrans.value();//根据字典映射关系转义字段值String transValue = mapping.get(value.toString();//设置转义值回字段field.set(joinPoint.getTarget(, transValue);}return result;}``````javapublic class Userprivate Integer gender;// getter and setter```5.在业务中使用转义后的字段值:```javapublic class UserService// 注入 UserMapper 或者其他数据访问层public User getUserById(String id)User user = userMapper.findById(id);System.out.println(user.getGender(); // 输出转义后的值,例如输出 "男"return user;}```这样,就实现了基于 SpringBoot、AOP 和自定义注解来转义字典值的功能。
【SpringFramework】Spring入门教程(三)使用注解配置
【SpringFramework】Spring⼊门教程(三)使⽤注解配置本⽂主要介绍四个⽅⾯:(1) 注解版本IOC和DI(2) Spring纯注解(3) Spring测试(4) SpringJDBC - Spring对数据库的操作使⽤注解配置Spring⼊门说在前⾯学习基于注解的IoC配置,⼤家脑海⾥⾸先得有⼀个认知,即注解配置和xml配置要实现的功能都是⼀样的,都是要降低模块间的耦合度。
仅仅只是配置的形式不⼀样。
关于实际的开发中到底使⽤xml还是注解,每家公司有着不同的使⽤习惯。
所以这两种配置⽅式我们都需要掌握。
基于注解配置的⽅式也已经逐渐代替xml配置。
所以我们必须要掌握使⽤注解的⽅式配置Spring。
配置步骤注意:如果使⽤Eclipse需要先安装了STS插件,或者使⽤STS开发⼯具创建项⽬。
本⽂使⽤IDEA进⾏演⽰。
1.2.1. 第⼀步:拷贝必备jar包到⼯程的lib⽬录。
注意:在基于注解的配置中,我们还要多拷贝⼀个aop的jar包。
如下图:1.2.2. 第⼆步:在类的根路径下创建⼀个任意名称的xml⽂件(不能是中⽂)注意:基于注解整合时,Spring配置⽂件导⼊约束时需要多导⼊⼀个context命名空间下的约束。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context.xsd"></beans>1.2.3. 第⼆步:创建⼀个服务类创建⼀个测试的服务类,并且加⼊使⽤@Component注解,声明该类允许注⼊到Spring容器package org.cjw.service;import ponent;/*使⽤注解配置时,需要将Spring框架启动就创建对象的类表⽰为组件类表⽰组件类使⽤@Component注解*/@Componentpublic class CustomerService {public void save() {System.out.println("-保存数据-");}}1.2.4. 第四步在spring的配置⽂件加⼊扫描注解<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context.xsd"><!-- 声明扫描包及其⼦包的类,如果发现有组件注解的类,就创建对象并加⼊到容器中去 --><context:component-scan base-package="org.cjw" /></beans>1.2.5. 第五步:测试调⽤代码package org.cjw.test;import org.cjw.service.CustomerService;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class CustomerServiceTest {@Testpublic void testSave() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");CustomerService customerService = context.getBean(CustomerService.class);customerService.save();}}--测试结果,如果可以调⽤服务⽅法,测试成功。
SpringAOP的原理和应用场景
SpringAOP的原理和应用场景SpringAOP(Aspect-Oriented Programming)是Spring框架中的一个重要组成部分,它提供了一种通过预定义的方式,将横切关注点(Cross-cutting Concerns)与业务逻辑进行解耦的机制。
本文将介绍SpringAOP的原理及其在实际应用场景中的应用。
一、SpringAOP的原理SpringAOP基于代理模式(Proxy Pattern)实现。
在SpringAOP中,通过生成与原始类(被代理类)具有相同接口的代理类,将横切逻辑编织到业务逻辑中。
在运行时,当调用代理类的方法时,会在方法执行前、后或异常抛出时插入相应的横切逻辑代码。
具体而言,SpringAOP使用了以下几个核心概念:1. 切面(Aspect):切面是横切逻辑的模块化单元,它包含了一组通知(Advice)和切点(Pointcut)。
2. 通知(Advice):通知定义了实际的横切逻辑代码,并规定了何时执行该代码。
SpringAOP提供了五种类型的通知:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。
3. 切点(Pointcut):切点指定了在哪些连接点(Join Point)上执行通知。
连接点可以是方法调用、属性访问等程序执行的点。
4. 连接点(Join Point):连接点是程序执行过程中的一个特定点,如方法调用前、方法调用后等。
通知通过切点来选择连接点。
5. 织入(Weaving):织入是将切面应用到目标对象,并创建代理对象的过程。
织入可以在编译时、类加载时或运行时进行。
二、SpringAOP的应用场景SpringAOP可应用于各种场景,用于解决跨越多个模块或类的横切关注点问题。
以下是一些常见的SpringAOP应用场景:1. 日志记录:通过在关键方法的前后插入日志代码,实现对系统运行状态的监控和记录。
aop的原理应用
AOP的原理应用1. 什么是AOPAOP(Aspect-Oriented Programming)是面向切面编程的缩写,它是一种能够通过解耦的方式将横切性关注点模块化的编程范式。
传统的面向对象编程(OOP)主要是通过类和对象来划分和组织代码,但当系统变得复杂时,代码中常常散布着一些与主要业务逻辑无关的、可复用的逻辑(比如日志记录、安全控制、事务管理等),这就导致了代码的重复和耦合度的增加。
而AOP可以通过将这些横切逻辑(称为切面)与主要业务逻辑分离,从而提高代码的可维护性、可测试性和可复用性。
2. AOP的原理AOP的核心原理是在编译期、加载期或运行期利用动态代理技术来实现切面的织入。
具体来说,AOP框架会在目标对象的方法调用前后或者异常抛出时,插入横切逻辑(切面),从而实现对目标对象的增强。
其中,横切逻辑通过切面由切点和增强组成。
•切点:定义了在何处插入切面的准则,比如可以根据类名、方法名或注解等进行精确定位。
•增强:指的是横切逻辑的实现,比如可以在方法调用前后执行某些操作。
织入过程可以通过前置织入、后置织入等方式来实现。
3. AOP的应用场景AOP的特点使得它在很多场景下都能够发挥作用,以下列举了几个常见的应用场景:•日志记录:AOP可以很方便地将日志记录逻辑与主要业务逻辑分离,从而使得代码更加清晰、易于维护。
例如,可以利用AOP在方法调用前后记录方法的输入参数和返回结果。
•安全控制:通过AOP可以在方法调用前进行身份验证、权限检查等安全控制逻辑,从而确保系统的安全性。
•事务管理:AOP可以在方法调用前后添加事务管理逻辑,保证数据的一致性和完整性。
例如,可以在方法调用前开启事务,在方法调用后提交或回滚事务。
•性能监控:利用AOP可以在方法调用前后统计方法的执行时间、请求次数等,通过监控这些性能指标可以优化系统的性能。
•异常处理:AOP可以在方法抛出异常时进行异常处理逻辑,并且可以根据异常类型进行不同的处理。
SpringAOP示例与实现原理总结——传统springaop、基于切面注入、基于@Asp。。。
SpringAOP⽰例与实现原理总结——传统springaop、基于切⾯注⼊、基于@Asp。
⼀、代码实践1)经典的Spring Aop经典的spring aop,是基于动态代理技术的。
实现⽅式上,最常⽤的是实现MethodInterceptor接⼝来提供环绕通知,创建若⼲代理,然后使⽤ProxyBeanFactory配置⼯⼚bean,⽣成拦截器链,完成拦截。
⽰例如下:1package demo.spring;23import org.aopalliance.intercept.MethodInterceptor;4import org.aopalliance.intercept.MethodInvocation;5import org.junit.Test;6import org.junit.runner.RunWith;7import org.springframework.beans.factory.annotation.Autowired;8import org.springframework.test.context.ContextConfiguration;9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;1011 @RunWith(SpringJUnit4ClassRunner.class)12 @ContextConfiguration("classpath:spring-config.xml")13public class TraditionalSpringAopDemo {14 @Autowired15private Service proxy;1617 @Test18public void test() {19 proxy.execute("hello world!");20 }21 }2223interface Service {24void execute(String str);25 }2627class ServiceImpl implements Service {28 @Override29public void execute(String str) {30 System.out.println("execute invoke: " + str);31 }32 }3334class Interceptor1 implements MethodInterceptor {35 @Override36public Object invoke(MethodInvocation methodInvocation) throws Throwable {37 System.out.println("interceptor1,before invoke");38 Object ret = methodInvocation.proceed();39 System.out.println("interceptor1,after invoke");40return ret;41 }42 }4344class Interceptor2 implements MethodInterceptor {45 @Override46public Object invoke(MethodInvocation methodInvocation) throws Throwable {47 System.out.println("interceptor2,before invoke");48 Object ret = methodInvocation.proceed();49 System.out.println("interceptor2,after invoke");50return ret;51 }52 }xml⽂件配置:1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="/schema/beans"3 xmlns:xsi="/2001/XMLSchema-instance"4 xmlns:context="/schema/context"5 xmlns:aop="/schema/aop"6 xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/sprin 78<context:component-scan base-package="demo.spring"/>910<bean class="demo.spring.ServiceImpl" id="service"></bean>11<bean class="demo.spring.Interceptor1" id="interceptor1"></bean>12<bean class="demo.spring.Interceptor2" id="interceptor2"></bean>13<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxy">14<property name="target" ref="service"/>15<property name="interceptorNames">16<list>17<value>interceptor1</value>18<value>interceptor2</value>19</list>20</property>21</bean>22</beans>结果:interceptor1,before invokeinterceptor2,before invokeexecute invoke: hello world!interceptor2,after invokeinterceptor1,after invoke可以看到拦截链的执⾏过程与拦截器顺序的关系。
AOP配置(含注解)详解
AOP配置(含注解)详解AOP(Aspect-Oriented Programming)是面向切面编程的缩写,是一种通过将横切关注点(cross-cutting concern)从业务逻辑代码中分离出来的编程思想和技术。
AOP通过在程序中定义切点(Join point)和通知(Advice),可以在不修改原有代码的情况下,对系统进行横向扩展,实现一些跨越多个对象和模块的功能。
AOP可以通过XML配置或者注解配置来实现,下面将以注解配置为例进行详细解析。
首先,我们需要在项目中引入相关的AOP依赖,如Spring AOP。
然后,我们需要在Spring的配置文件中启用AOP功能,这可以通过在配置文件中添加`<aop:aspectj-autoproxy/>`来实现。
这样,Spring就会自动扫描并自动生成代理类以实现AOP。
接下来,我们需要定义切点和通知。
切点是在程序中定义的一些特定的方法,它们可以被AOP框架所拦截。
通知则是在切点被拦截时执行的一段代码。
除了切面、切点和通知,AOP还涉及到一些其他的概念,如切入点、连接点和增强器。
切入点是一个或多个切点的集合,用于定义一组相关的切点。
连接点是在程序中与切点相匹配的特定位置,如方法的执行点。
增强器则是在通知被调用之前或之后,对连接点进行拦截并执行相应的通知。
总之,AOP通过在程序中定义切点和通知,可以实现对系统中特定方法的拦截和增强。
它可以很好地解耦系统的各个模块,并提供了一种便捷的方式来实现横切关注点的功能。
需要注意的是,AOP是一种非常强大和灵活的编程思想和技术,它可以用于很多方面,如日志记录、性能监控、安全检查等。
在使用AOP时,需要充分考虑系统的复杂性和可维护性,避免过度使用AOP,以免产生不必要的复杂性和难以维护的代码。
同时,需要合理地选择切点和通知,保持代码的简洁和可读性。
Spring中IOC和AOP的深入讲解
Spring中IOC和AOP的深⼊讲解前⾔Spring是⼀个开源框架,Spring是于2003 年兴起的⼀个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍⽣⽽来。
它是为了解决企业应⽤开发的复杂性⽽创建的。
Spring使⽤基本的JavaBean来完成以前只可能由EJB完成的事情。
然⽽,Spring的⽤途不仅限于服务器端的开发。
从简单性、可测试性和松耦合的⾓度⽽⾔,任何Java应⽤都可以从Spring中受益。
简单来说,Spring是⼀个轻量级的控制反转(IoC)和⾯向切⾯(AOP)的容器框架。
这篇⽂章主要讲 Spring 中的⼏个点,Spring 中的 IOC,AOP,下⼀篇说说 Spring 中的事务操作,注解和 XML 配置。
Spring 简介Spring 是⼀个开源的轻量级的企业级框架,其核⼼是反转控制 (IoC) 和⾯向切⾯ (AOP) 的容器框架。
我们可以把 Spring 看成是对象的容器,容器中可以包含很多对象,所以 Spring 有很多强⼤的功能。
⼀句话,Spring 是项⽬中对象的管家,负责管理项⽬中⽤到的所有对象。
所以在项⽬三层架构中,Spring 不属于某⼀特定层。
Spring 的 Hello World想要构建⼀个 Spring 的⼊门程序,我们需要导⼊ 4 个核⼼包和 2 个辅助包,创建⼀个实体类,最主要的是编写核⼼配置⽂件,applicationContext.xml 放在 src 下。
最后写⼀个测试类即可。
此时在测试类中我们不需要在使⽤ new 关键字去创建对象了。
这也正是 Spring 的作⽤所在,会⾃动给我创建对象。
上图展⽰的就是最基本的演⽰,也是很容易就理解了,配置⽂件中配置了 user 对象,我们通过加载配置⽂件来获取对象从⽽避免了使⽤ new 来创建。
SpringAOP切面日志Demo配置文件方式与注解方式
SpringAOP切⾯⽇志Demo配置⽂件⽅式与注解⽅式⼀、配置⽂件⽅式1、配置applicationContext.xml,<bean id="logAopBean"class="mon.aop.LogAop"></bean><aop:config><aop:aspect id="logAspect"ref="logAopBean"><aop:pointcut expression="execution(* com.demo..*(..))" id="allMethod"/><aop:before method="before" pointcut-ref="allMethod" /><aop:after-throwing method="afterThrowing" pointcut-ref="allMethod" /><aop:after-returning method="afterReturn" pointcut-ref="allMethod" /><aop:after method="after" pointcut-ref="allMethod" /></aop:aspect></aop:config>2、⽇志处理类,/*** LogAop.java** Shanghai NTT DATA Synergy Software Co., Ltd. All Rights Reserved.* @author wyl* @date 2016-10-18*/package mon.aop;import ng.JoinPoint;import ng.ProceedingJoinPoint;/*** @author wyl* @Description TODO* @date 2016-10-18**/public class LogAop {public void before(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println("开始执⾏:"+className+"."+methodName+"()⽅法...");}public void afterThrowing(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法抛出了异常...");}public void afterReturn(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法正常执⾏结束...");}public void after(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()最终执⾏步骤(finally)...");}/*//⽤来做环绕通知的⽅法可以第⼀个参数定义为ng.ProceedingJoinPoint类型public Object doAround(ProceedingJoinPoint call) throws Throwable {Object result = null;this.before(call);//相当于前置通知try {result = call.proceed();this.afterReturn(call); //相当于后置通知} catch (Throwable e) {this.afterThrowing(call); //相当于异常抛出后通知throw e;}finally{this.after(call); //相当于最终通知}return result;}*/}⼆、注解⽅式1、配置applicationContext.xml,<bean id="logAspectBean"class="mon.aop.LogAnnotationAspect"></bean> <aop:aspectj-autoproxy/>2、⽇志处理类,/*** LogAnnotationAspect.java** Shanghai NTT DATA Synergy Software Co., Ltd. All Rights Reserved.* @author wyl* @date 2016-10-18*/package mon.aop;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.annotation.After;import ng.annotation.AfterReturning;import ng.annotation.AfterThrowing;import ng.annotation.Aspect;import ng.annotation.Before;import ng.annotation.Pointcut;/*** @author wyl* @Description TODO* @date 2016-10-18**/@Aspect //定义切⾯类public class LogAnnotationAspect {@SuppressWarnings("unused")//定义切⼊点,提供⼀个⽅法,这个⽅法的名字就是改切⼊点的id@Pointcut("execution(* com.demo..*(..))")private void allMethod(){}//针对指定的切⼊点表达式选择的切⼊点应⽤前置通知@Before("allMethod()")public void before(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println("开始执⾏:"+className+"."+methodName+"()⽅法...");}//访问命名切⼊点来应⽤后置通知@AfterReturning("allMethod()")public void afterReturn(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法正常执⾏结束...");}//应⽤最终通知@After("allMethod()")public void after(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()最终执⾏步骤(finally)...");}//应⽤异常抛出后通知@AfterThrowing("allMethod()")public void afterThrowing(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法抛出了异常...");}//应⽤周围通知//@Around("allMethod()")public Object doAround(ProceedingJoinPoint call) throws Throwable{Object result = null;this.before(call);//相当于前置通知try {result = call.proceed();this.afterReturn(call); //相当于后置通知} catch (Throwable e) {this.afterThrowing(call); //相当于异常抛出后通知throw e;}finally{this.after(call); //相当于最终通知}return result;}}。
AOP事务管理的原理与及三种实现方式
AOP事务管理的原理与及三种实现方式AOP(Aspect-Oriented Programming)即面向切面编程,是一种软件开发方法,主要用于解决分散在一个应用程序中的横切关注点(cross-cutting concerns)问题。
事务管理是AOP的一个典型应用场景,它主要用于保证一系列操作的原子性、一致性和隔离性。
本文将详细介绍AOP事务管理的原理以及三种常见的实现方式。
一、AOP事务管理原理1.拦截器执行顺序首先,AOP框架通过拦截器机制,将事务相关的拦截器按照一定的顺序进行执行。
常见的拦截器有前置拦截器(Before)、后置拦截器(After)、异常拦截器(AfterThrowing)、返回拦截器(AfterReturning)等。
2.事务传播和隔离级别在方法级别的事务管理中,每个被拦截的方法可以有不同的事务传播行为和隔离级别。
事务传播行为指的是当一个方法调用另外一个方法时,如何处理事务;隔离级别指的是事务之间的隔离程度。
3.事务切面的应用通过拦截器机制,将事务注解或者配置文件中的事务属性传递给事务管理器,然后由事务管理器根据事务属性进行事务操作。
实际应用中,可以使用Spring框架提供的AOP事务管理功能来实现对方法级别的事务控制。
根据AOP事务管理的原理,常见的AOP事务管理的实现方式有基于注解的方式、基于XML配置的方式和基于编程的方式。
1.基于注解的方式优点:(1)简单方便,只需在方法上加上注解即可进行事务管理。
(2)灵活可控,通过注解可以更细粒度地控制事务的传播行为和隔离级别。
(3)清晰明了,注解能够直观地体现出事务的特性。
缺点:(1)侵入性较强,需要在代码中添加注解。
(2)不能对第三方库中的方法进行事务管理。
2.基于XML配置的方式基于XML配置的方式是通过在配置文件中定义事务管理器、事务通知以及切点表达式等信息,来实现对方法级别的事务控制。
通过AOP框架读取配置文件,将事务相关的信息应用到需要进行事务管理的方法上。
使用spring通过aop获取方法参数和参数值
使⽤spring通过aop获取⽅法参数和参数值⽬录spring通过aop获取⽅法参数和参数值⾃定义注解切⾯aop切⾯注解、参数获取1、定义需要切⾯的注解2、在需要进⾏切⾯的⽅法标注注解3、定义切⾯spring通过aop获取⽅法参数和参数值⾃定义注解package com.xiaolc.aspect;import ng.annotation.*;/*** @author lc* @date 2019/9/10*/@Documented@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface LiCheng {}切⾯package com.xiaolc.aspect;import ng.ProceedingJoinPoint;import ng.annotation.Around;import ng.annotation.Aspect;import org.springframework.core.DefaultParameterNameDiscoverer;import org.springframework.core.ParameterNameDiscoverer;import ponent;import ng.reflect.Method;import java.util.HashMap;import java.util.Map;/*** 获取⽅法上的注解值*/@Component@Aspectpublic class AuditAnnotationAspect {@Around("@annotation(liCheng))")private static Map getFieldsName(ProceedingJoinPoint joinPoint,LiCheng liCheng) throws ClassNotFoundException, NoSuchMethodException { String classType = joinPoint.getTarget().getClass().getName();String methodName = joinPoint.getSignature().getName();// 参数值Object[] args = joinPoint.getArgs();Class<?>[] classes = new Class[args.length];for (int k = 0; k < args.length; k++) {if (!args[k].getClass().isPrimitive()) {// 获取的是封装类型⽽不是基础类型String result = args[k].getClass().getName();Class s = map.get(result);classes[k] = s == null ? args[k].getClass() : s;}}ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();// 获取指定的⽅法,第⼆个参数可以不传,但是为了防⽌有重载的现象,还是需要传⼊参数的类型Method method = Class.forName(classType).getMethod(methodName, classes);// 参数名String[] parameterNames = pnd.getParameterNames(method);// 通过map封装参数和参数值HashMap<String, Object> paramMap = new HashMap();for (int i = 0; i < parameterNames.length; i++) {paramMap.put(parameterNames[i], args[i]);System.out.println("参数名:"+parameterNames[i]+"\n参数值"+args[i]);}return paramMap;}private static HashMap<String, Class> map = new HashMap<String, Class>() {{put("ng.Integer", int.class);put("ng.Double", double.class);put("ng.Float", float.class);put("ng.Long", Long.class);put("ng.Short", short.class);put("ng.Boolean", boolean.class);put("ng.Char", char.class);}};}aop切⾯注解、参数获取在⼯作中会经常使⽤aop,这⾥将aop使⽤基本⽅法,获取在切点中使⽤的获取参数、注解做⼀个样例。
aop使用方法
aop使用方法
AOP (Aspect Oriented Programming)的使用方法可以分为以下几个步骤:
1. 引入AOP框架:可以使用Java中的Spring框架、AspectJ 等AOP框架,根据项目需求选择适合的框架,并将其引入到项目中。
2. 定义关注点(Concerns):确定需要在系统中进行跟踪或监控的横切业务逻辑,如日志记录、安全检查、事务管理等。
3. 编写切面(Aspect):切面是关注点的具体实现,它定义了在何处以及如何将关注点插入到应用程序中。
切面由一系列的通知(Advices)和切点(Pointcuts)组成。
4. 编写通知(Advice):通知定义了在切点处执行的操作,如在切点前、切点后、切点周围等进行操作。
常见的通知类型有@Before、@After、@Around、@AfterReturning和
@AfterThrowing等。
5. 定义切点(Pointcut):切点是一个表达式,它确定了哪些方法需要应用通知。
可以使用表达式语言或编程语言的语法来定义切点。
6. 注入切面:将切面注入到目标对象中,在需要应用关注点的方法上添加切点,让切点与方法关联起来。
7. 配置AOP:在配置文件中或使用注解的方式配置AOP,在配置中定义切点和通知之间的关系以及切点的执行顺序。
8. 运行应用程序:通过运行应用程序,AOP框架将会根据切面的配置,在切点处自动插入通知并执行。
以上是AOP的基本使用方法,根据具体的需求和AOP框架的特性,可能会有一些细微的差别,但整体思路是类似的。
springboot引入AOP切面@Aspect注解使用
springboot引⼊AOP切⾯@Aspect注解使⽤<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>*/@Aspect@Component@Slf4jpublic class HttpAspect {/*** ⽇志切点*/@Pointcut("execution(public * com.api.controller..*.*(..))")public void log() {}/*** 开始请求前** @param joinPoint*/@Before("log()")public void doBefore(JoinPoint joinPoint) {// 主类ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if (attributes != null){HttpServletRequest request = attributes.getRequest();// url 路径("请求={}", request.getRequestURL() + " | method=" + request.getMethod() + " | ip=" + request.getRemoteAddr());// 类⽅法("⽅法={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());// 参数("参数={}", Arrays.toString(joinPoint.getArgs()));}}/*** 返回处理** @param result*/@AfterReturning(returning = "result", pointcut = "log()")public void doAfterReturning(Object result) {("返回={}", JSON.toJSON(result));}任何的public⽅法execution(public * *(..))以set开始的⽅法execution(* set*(..))定义在cn.freemethod.business.pack.Say接⼝中的⽅法execution(* cn.freemethod.business.pack.Say.*(..))任何cn.freemethod.business包中的⽅法execution(* cn.freemethod.business.*.*(..))任何定义在com.xyz.service包或者其⼦包中的⽅法execution(* cn.freemethod.business..*.*(..))其他表达式任何在com.xyz.service包中的⽅法within(com.xyz.service.*)任何定义在com.xyz.service包或者其⼦包中的⽅法within(com.xyz.service..*)任何实现了com.xyz.service.AccountService接⼝中的⽅法this(com.xyz.service.AccountService)任何⽬标对象实现了com.xyz.service.AccountService的⽅法target(com.xyz.service.AccountService)⼀般情况下代理类(Proxy)和⽬标类(Target)都实现了相同的接⼝,所以上⾯的2个基本是等效的。
Java框架------Spring框架AOP注解(@Aspect和@Around)
Java框架------Spring框架AOP注解(@Aspect和@Around)AOP 中的声明主要有两种基于XML和基于Annotation之前的为借助xml ,现在介绍⼀下借助注解的⽅式,修改之前的⼩项⽬常见五种通知类型org.springframework.aop.MethodBeforeAdvice(前置通知)在⽅法之前⾃动执⾏的通知称为前置通知,可以应⽤于权限管理等功能。
org.springframework.aop.AfterReturningAdvice(后置通知)在⽅法之后⾃动执⾏的通知称为后置通知,可以应⽤于关闭流、上传⽂件、删除临时⽂件等功能。
org.aopalliance.intercept.MethodInterceptor(环绕通知)在⽅法前后⾃动执⾏的通知称为环绕通知,可以应⽤于⽇志、事务管理等功能。
org.springframework.aop.ThrowsAdvice(异常通知)在⽅法抛出异常时⾃动执⾏的通知称为异常通知,可以应⽤于处理异常记录⽇志等功能。
org.springframework.aop.IntroductionInterceptor(引介通知)在⽬标类中添加⼀些新的⽅法和属性,可以应⽤于修改旧版本程序(增强类)。
常见注解@Aspect:作⽤是把当前类标识为⼀个切⾯供容器读取@Around:环绕增强,相当于MethodInterceptor@AfterReturning:后置增强,相当于AfterReturningAdvice,⽅法正常退出时执⾏@Pointcut:Pointcut是植⼊Advice的触发条件。
每个Pointcut的定义包括2部分,⼀是表达式,⼆是⽅法签名。
⽅法签名必须是 public及void型。
可以将Pointcut中的⽅法看作是⼀个被Advice引⽤的助记符,因为表达式不直观,因此我们可以通过⽅法@Before:标识⼀个前置增强⽅法,相当于BeforeAdvice的功能,相似功能的还有@AfterThrowing:异常抛出增强,相当于ThrowsAdvice@After: final增强,不管是抛出异常或者正常退出都会执⾏使⽤pointcut代码@DeclareParents ⽤于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。
详解SpringBootAOP拦截器(Aspect注解方式)
详解SpringBootAOP拦截器(Aspect注解⽅式)常⽤⽤于实现拦截的有:Filter、HandlerInterceptor、MethodInterceptor第⼀种Filter属于Servlet提供的,后两者是spring提供的,HandlerInterceptor属于Spring MVC项⽬提供的,⽤来拦截请求,在MethodInterceptor之前执⾏。
实现⼀个HandlerInterceptor可以实现接⼝HandlerInterceptor,也可以继承HandlerInterceptorAdapter类,两种⽅法⼀样。
这个不在本⽂范围,具体使⽤之前已经写过SpringBoot的(SpringMVC的使⽤⼀样,区别只是配置)MethodInterceptor是AOP项⽬中的拦截器,它拦截的⽬标是⽅法,即使不是Controller中的⽅法。
实现MethodInterceptor拦截器⼤致也分为两种,⼀种是实现MethodInterceptor接⼝,另⼀种利⽤Aspect的注解或配置。
关于实现MethodInterceptor接⼝的这种⽅法,还需要在配置⽂件中做配置,在SpringMVC中使⽤还可以,在SpringBoot中使⽤起来似乎没有那么⽅便。
本⽂主要还是说Aspect注解⽅式,个⼈觉得这种⽅法才⽐较灵活,与配置与⼯程整个代码都没有耦合(你添加⼀个类,做⼏个注解就可以⽤了,⽆需在其他地⽅再做什么),更易应⽤。
⾸先为你的SpringBoot项⽬添加maven依赖,让其⽀持aop(其实就是⾃动引⼊aop需要的⼀些jar)在pom.xml中添加依赖:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>然后创建Aspect测试类:package com.shanhy.sboot.aop;import ng.JoinPoint;import ng.annotation.After;import ng.annotation.Aspect;import ng.annotation.Before;import org.springframework.core.annotation.Order;import ponent;@Aspect // FOR AOP@Order(-99) // 控制多个Aspect的执⾏顺序,越⼩越先执⾏@Componentpublic class TestAspect {@Before("@annotation(test)")// 拦截被TestAnnotation注解的⽅法;如果你需要拦截指定package指定规则名称的⽅法,可以使⽤表达式execution(...),具体百度⼀下资料⼀⼤堆 public void beforeTest(JoinPoint point, TestAnnotation test) throws Throwable {System.out.println("beforeTest:" + ());}@After("@annotation(test)")public void afterTest(JoinPoint point, TestAnnotation test) {System.out.println("afterTest:" + ());}}这样就完成了,然后创建⼀个Controller验证⼀下:@RestController@RequestMapping("/test")public class TestController {@TestAnnotation(name="abc")@RequestMapping("/show")public String show() {return "OK";}@RequestMapping("/show2")public String show2() {return "OK2";}}此时我们访问show请求,就会被拦截,控制台会打印输出。
Spring系列之AOP实现的两种方式
Spring系列之AOP实现的两种⽅式Spring只⽀持XML⽅式⽽没有实现注解的⽅式(也叫AspectJ⽅式)的AOP,所以要使⽤@Aspect注解,只能引⼊AspectJ相关的 jar 包:aopalliance-1.0.jar 和 aspectjweaver.jarSpring的配置⽂件 applicationContext.xml 中引⼊context、aop对应的命名空间;配置⾃动扫描的包,同时使切⾯类中相关⽅法中的注解⽣效,需⾃动地为匹配到的⽅法所在的类⽣成代理对象。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:aop="/schema/aop"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd/schema/aop /schema/aop/spring-aop-4.0.xsd/schema/context /schema/context/spring-context-4.0.xsd"><!-- 配置⾃动扫描的包 --><context:component-scan base-package="com.qcc.beans.aop"></context:component-scan><!-- ⾃动为切⾯⽅法中匹配的⽅法所在的类⽣成代理对象。
--><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>AOP常⽤的实现⽅式有两种,1、采⽤声明的⽅式来实现(基于XML),2、是采⽤注解的⽅式来实现(基于AspectJ)。
aop切面中或获取自定义注解中的参数
aop切面中或获取自定义注解中的参数AOP(面向切面编程)是一种编程思想,它允许开发人员在应用程序的不同层次上插入代码,以便在运行时对其进行拦截和修改。
在AOP中,切面是一组跨越多个类和方法的通用功能,例如日志记录、性能测量、安全性等。
在切面中,我们可以使用自定义注解来传递参数,以便更好地控制切面的行为。
下面是一些有关在AOP切面中或获取自定义注解中的参数的技巧:1. 使用@Around注解@Around注解是Spring AOP中最强大的注解之一。
它允许我们在方法执行之前和之后拦截方法调用,并在必要时修改方法参数和返回值。
在@Around注解中,我们可以使用ProceedingJoinPoint参数访问方法参数和方法签名,并使用它们来执行额外的操作。
2. 使用@Pointcut注解@Pointcut注解用于定义一个切点,即一组匹配的方法或类。
在@Pointcut注解中,我们可以使用自定义注解来指定要匹配的方法或类,并使用它们来定义切点。
例如,我们可以使用@Pointcut注解来定义一个切点,以便在所有被@Loggable注解的方法中添加日志记录。
3. 使用@Aspect注解@Aspect注解用于定义一个切面,即一组跨越多个类和方法的通用功能。
在@Aspect注解中,我们可以使用自定义注解来指定要匹配的方法或类,并使用它们来定义切面。
例如,我们可以使用@Aspect注解来定义一个切面,以便在所有被@Cacheable注解的方法中添加缓存逻辑。
4. 使用@Annotation注解@Annotation注解用于定义一个自定义注解,并将其与切面或切点相关联。
在@Annotation注解中,我们可以使用元注解@Target和@Retention来指定自定义注解的作用域和生命周期,并使用元注解@Inherited来指定自定义注解是否可以被子类继承。
例如,我们可以使用@Annotation注解来定义一个@Loggable注解,并将其与一个日志记录切面相关联。
Spring面试,IoC和AOP的理解,@Transactional原理及使用
Spring⾯试,IoC和AOP的理解,@Transactional原理及使⽤spring 的优点?1.降低了组件之间的耦合性,实现了软件各层之间的解耦2.可以使⽤容易提供的众多服务,如事务管理,消息服务等3.容器提供单例模式⽀持4.容器提供了AOP技术,利⽤它很容易实现如权限拦截,运⾏期监控等功能5.容器提供了众多的辅助类,能加快应⽤的开发6.spring对于主流的应⽤框架提供了集成⽀持,如hibernate,JPA,Struts等7.spring属于低侵⼊式设计,代码的污染极低8.独⽴于各种应⽤服务器9.spring的DI机制降低了业务对象替换的复杂性10.Spring的⾼度开放性,并不强制应⽤完全依赖于Spring,开发者可以⾃由选择spring的部分或全部什么是DI机制?依赖注⼊(Dependecy Injection)和控制反转(Inversion of Control)是同⼀个概念,具体的讲:当某个⾓⾊需要另外⼀个⾓⾊协助的时候,在传统的程序设计过程中,通常由调⽤者来创建被调⽤者的实例。
但在spring中创建被调⽤者的⼯作不再由调⽤者来完成,因此称为控制反转。
创建被调⽤者的⼯作由spring来完成,然后注⼊调⽤者因此也称为依赖注⼊。
spring以动态灵活的⽅式来管理对象,注⼊的两种⽅式,设置注⼊和构造注⼊。
设置注⼊的优点:直观,⾃然构造注⼊的优点:可以在构造器中决定依赖关系的顺序。
什么是AOP?⾯向切⾯编程(AOP)完善spring的依赖注⼊(DI),⾯向切⾯编程在spring中主要表现为两个⽅⾯1.⾯向切⾯编程提供声明式事务管理2.spring⽀持⽤户⾃定义的切⾯⾯向切⾯编程(aop)是对⾯向对象编程(oop)的补充,⾯向对象编程将程序分解成各个层次的对象,⾯向切⾯编程将程序运⾏过程分解成各个切⾯。
AOP从程序运⾏⾓度考虑程序的结构,提取业务处理过程的切⾯,oop是静态的抽象,aop是动态的抽象,是对应⽤执⾏过程中的步骤进⾏抽象,,从⽽获得步骤之间的逻辑划分。
SpringBoot使用@Aspect注解实现AOP
SpringBoot使⽤@Aspect注解实现AOPAOP(Aspect Oriented Programming,⾯向切⾯编程)是通过预编译⽅式和运⾏期动态代理实现程序功能的统⼀维护的⼀种技术。
AOP是OOP的延续,是软件开发中的⼀个热点,也是Spring框架中的⼀个重要内容,是函数式编程的⼀种衍⽣范型。
利⽤AOP可以对业务逻辑的各个部分进⾏隔离,从⽽使得业务逻辑各部分之间的耦合度降低,提⾼程序的可重⽤性,同时提⾼了开发的效率。
在Spring AOP中业务逻辑仅仅只关注业务本⾝,将⽇志记录、性能统计、安全控制、事务处理、异常处理等代码从业务逻辑代码中划分出来,从⽽在改变这些⾏为的时候不影响业务逻辑的代码。
相关注解介绍:注解作⽤@Aspect把当前类标识为⼀个切⾯@Pointcut Pointcut是织⼊Advice的触发条件。
每个Pointcut的定义包括2部分,⼀是表达式,⼆是⽅法签名。
⽅法签名必须是public及void 型。
可以将Pointcut中的⽅法看作是⼀个被Advice引⽤的助记符,因为表达式不直观,因此我们可以通过⽅法签名的⽅式为此表达式命名。
因此Pointcut中的⽅法只需要⽅法签名,⽽不需要在⽅法体内编写实际代码。
@Around环绕增强,⽬标⽅法执⾏前后分别执⾏⼀些代码@AfterReturning返回增强,⽬标⽅法正常执⾏完毕时执⾏@Before前置增强,⽬标⽅法执⾏之前执⾏@AfterThrowing异常抛出增强,⽬标⽅法发⽣异常的时候执⾏@After后置增强,不管是抛出异常或者正常退出都会执⾏⼀、添加依赖<!--Spring AOP 切⾯模块 --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId></dependency><!-- SpringBoot 拦截器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency>⼆、编写增强类package com.example.demo.Aspect;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import lombok.extern.slf4j.Slf4j;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.Signature;import ng.annotation.*;import ng.reflect.SourceLocation;import ponent;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.util.Arrays;@Component@Aspect@Slf4jpublic class LogAspect {private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();@Pointcut("execution(* com.example.demo.Aspect.TestController.doNormal(..))")public void pointCut(){}@Before(value = "pointCut()")public void before(JoinPoint joinPoint){("@Before通知执⾏");//获取⽬标⽅法参数信息Object[] args = joinPoint.getArgs();Arrays.stream(args).forEach(arg->{ // ⼤⼤try {(OBJECT_MAPPER.writeValueAsString(arg));} catch (JsonProcessingException e) {(arg.toString());}});//aop代理对象Object aThis = joinPoint.getThis();(aThis.toString()); //com.xhx.springboot.controller.HelloController@69fbbcdd//被代理对象Object target = joinPoint.getTarget();(target.toString()); //com.xhx.springboot.controller.HelloController@69fbbcdd//获取连接点的⽅法签名对象Signature signature = joinPoint.getSignature();(signature.toLongString()); //public ng.String com.xhx.springboot.controller.HelloController.getName(ng.String) (signature.toShortString()); //HelloController.getName(..)(signature.toString()); //String com.xhx.springboot.controller.HelloController.getName(String)//获取⽅法名(signature.getName()); //getName//获取声明类型名(signature.getDeclaringTypeName()); //com.xhx.springboot.controller.HelloController//获取声明类型⽅法所在类的class对象(signature.getDeclaringType().toString()); //class com.xhx.springboot.controller.HelloController//和getDeclaringTypeName()⼀样(signature.getDeclaringType().getName());//com.xhx.springboot.controller.HelloController//连接点类型String kind = joinPoint.getKind();(kind);//method-execution//返回连接点⽅法所在类⽂件中的位置打印报异常SourceLocation sourceLocation = joinPoint.getSourceLocation();(sourceLocation.toString());//(sourceLocation.getFileName());//(sourceLocation.getLine()+"");//(sourceLocation.getWithinType().toString()); //class com.xhx.springboot.controller.HelloController///返回连接点静态部分JoinPoint.StaticPart staticPart = joinPoint.getStaticPart();(staticPart.toLongString()); //execution(public ng.String com.xhx.springboot.controller.HelloController.getName(ng.String))//attributes可以获取request信息 session信息等ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();(request.getRequestURL().toString()); //http://127.0.0.1:8080/hello/getName(request.getRemoteAddr()); //127.0.0.1(request.getMethod()); //GET("before通知执⾏结束");}/*** 后置返回* 如果第⼀个参数为JoinPoint,则第⼆个参数为返回值的信息* 如果第⼀个参数不为JoinPoint,则第⼀个参数为returning中对应的参数* returning:限定了只有⽬标⽅法返回值与通知⽅法参数类型匹配时才能执⾏后置返回通知,否则不执⾏,* 参数为Object类型将匹配任何⽬标返回值*/@AfterReturning(value = "pointCut()",returning = "result")public void doAfterReturningAdvice1(JoinPoint joinPoint,Object result){("第⼀个后置返回通知的返回值:"+result);}@AfterReturning(value = "pointCut()",returning = "result",argNames = "result")public void doAfterReturningAdvice2(String result){("第⼆个后置返回通知的返回值:"+result);}//第⼀个后置返回通知的返回值:姓名是⼤⼤//第⼆个后置返回通知的返回值:姓名是⼤⼤//第⼀个后置返回通知的返回值:{name=⼩⼩, id=1}/*** 后置异常通知* 定义⼀个名字,该名字⽤于匹配通知实现⽅法的⼀个参数名,当⽬标⽅法抛出异常返回后,将把⽬标⽅法抛出的异常传给通知⽅法;* throwing:限定了只有⽬标⽅法抛出的异常与通知⽅法相应参数异常类型时才能执⾏后置异常通知,否则不执⾏,* 对于throwing对应的通知⽅法参数为Throwable类型将匹配任何异常。
(10条消息)springboot自定义注解使用AOP实现请求参数解密以及响应数据加密
(10条消息)springboot⾃定义注解使⽤AOP实现请求参数解密以及响应数据加密⼀、前⾔本篇⽂章将依托与SpringBoot平台,⾃定义注解⽤来标识接⼝请求是否实现加密解密。
使⽤AOP切⾯来具体操作解密加密,实现对源代码的低耦合,不在原基础上做很⼤的改动。
本篇⽂章的所有⽰例,都上传到我的github中,欢迎⼤家拉取测试,欢迎star github实现要求:1. ⾃定义⼀个注解@Secret,⽤来标识需要实现加密解密作⽤在Controller类上,表⽰此Controller类的所有接⼝都实现加密解密作⽤来单⼀⽅法上,表⽰此接⼝⽅法需要实现加密解密2. 使⽤AOP切⾯编程实现在接⼝⽅法执⾏之前将前端的加密参数解密并重新赋给接⼝参数在接⼝⽅法响应之后,将返回的数据进⾏加密返回3. 在配置⽂件中配置,是否开启全局的加密解密操作实现流程:1. 前端请求的接⼝将请求参数json通过AES加密⽣成加密字符串,然后将加密字符串通过名为encyptStr字段传递给后端。
2. AOP前置⽅法拦截,将encyptStr字符串通过AES解密得到原始请求参数json,将json映射为请求⽅法的参数对象User。
3. 接⼝通过参数成功响应,并将响应数据直接返回。
4. AOP后置⽅式拦截,将响应参数data字段⾥的数据AES加密,并返回给前端5. 前端收到请求响应,通过code判断请求是否成功,AES加密data字段得到需要的数据。
⼆、实现操作1. 创建SPRINGBOOT项⽬创建⼀个SpringBoot项⽬,导⼊必要的maven依赖。
使⽤AOP切⾯需要导⼊AOP的启动器lombok是⼀个通过注解简化代码的⼯具,在idea中使⽤需要安装lombok插件json转换⼯具,apache⼯具类pom.xml1. <!-- web依赖 -->2. <dependency>3. <groupId>org.springframework.boot</groupId>4. <artifactId>spring-boot-starter-web</artifactId>5. </dependency>6.7. <!-- AOP切⾯依赖 -->8. <dependency>9. <groupId>org.springframework.boot</groupId>10. <artifactId>spring-boot-starter-aop</artifactId>11. </dependency>12.13. <!-- lombok⼯具 -->14. <dependency>15. <groupId>org.projectlombok</groupId>16. <artifactId>lombok</artifactId>17. <optional>true</optional>18. </dependency>19.20. <!-- json操作类 -->21. <dependency>22. <groupId>com.alibaba</groupId>23. <artifactId>fastjson</artifactId>24. <version>1.2.52.sec06</version>25. </dependency>26. <!-- String⼯具包 -->27. <dependency>28. <groupId>mons</groupId>29. <artifactId>commons-lang3</artifactId>30. <version>3.9</version>31. </dependency>2. ⾃定注解@SECRET我们通过⾃定义的注解,来标识类或接⼝,告诉AOP哪些类或⽅法需要执⾏加密解密操作,更加的灵活。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于注解的Spring AOP的配置和使用AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程。
可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。
我们现在做的一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP就实现了把这些业务需求与系统需求分开来做。
这种解决的方式也称代理机制。
先来了解一下AOP的相关概念,《Spring参考手册》中定义了以下几个AOP的重要概念,结合以上代码分析如下:∙切面(Aspect):官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”,在本例中,“切面”就是类TestAspect所关注的具体行为,例如,AServiceImpl.barA()的调用就是切面TestAspect所关注的行为之一。
“切面”在ApplicationContext 中<aop:aspect>来配置。
∙连接点(Joinpoint):程序执行过程中的某一行为,例如,UserService.get 的调用或者UserService.delete抛出异常等行为。
∙通知(Advice):“切面”对于某个“连接点”所产生的动作,例如,TestAspect 中对com.spring.service包下所有类的方法进行日志记录的动作就是一个Advice。
其中,一个“切面”可以包含多个“Advice”,例如ServiceAspect。
∙切入点(Pointcut):匹配连接点的断言,在AOP中通知和一个切入点表达式关联。
例如,TestAspect中的所有通知所关注的连接点,都由切入点表达式execution(* com.spring.service.*.*(..))来决定。
∙目标对象(Target Object):被一个或者多个切面所通知的对象。
例如,AServcieImpl和BServiceImpl,当然在实际运行时,Spring AOP采用代理实现,实际AOP操作的是TargetObject的代理对象。
∙AOP代理(AOP Proxy):在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。
默认情况下,TargetObject实现了接口时,则采用JDK动态代理,例如,AServiceImpl;反之,采用CGLIB代理,例如,BServiceImpl。
强制使用CGLIB代理需要将 <aop:config>的 proxy-target-class属性设为true。
通知(Advice)类型:∙前置通知(Before advice):在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。
ApplicationContext中在<aop:aspect>里面使用<aop:before>元素进行声明。
例如,TestAspect中的doBefore方法。
∙后置通知(After advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
ApplicationContext中在<aop:aspect>里面使用<aop:after>元素进行声明。
例如,ServiceAspect中的returnAfter方法,所以Teser中调用 UserService.delete抛出异常时,returnAfter方法仍然执行。
∙返回后通知(After return advice):在某连接点正常完成后执行的通知,不包括抛出异常的情况。
ApplicationContext中在<aop:aspect>里面使用<after-returning>元素进行声明。
∙环绕通知(Around advice):包围一个连接点的通知,类似Web中Servlet 规范中的Filter的doFilter方法。
可以在方法的调用前后完成自定义的行为,也可以选择不执行。
ApplicationContext中在<aop:aspect>里面使用<aop:around>元素进行声明。
例如,ServiceAspect中的around方法。
∙抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。
ApplicationContext中在<aop:aspect>里面使用<aop:after-throwing>元素进行声明。
例如,ServiceAspect中的returnThrow方法。
注:可以将多个通知应用到一个目标对象上,即可以将多个切面织入到同一目标对象。
使用Spring AOP可以基于两种方式,一种是比较方便和强大的注解方式,另一种则是中规中矩的xml配置方式。
先说注解,使用注解配置Spring AOP总体分为两步,第一步是在xml文件中声明激活自动扫描组件功能,同时激活自动代理功能(同时在xml中添加一个UserService的普通服务层组件,来测试AOP的注解功能):<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/aop /schema/aop/spring-aop-3.1.xsd/schema/beans http://ww /schema/beans/spring-beans.xsd/schema/context http:// /schema/context/spring-context-3.0.xsd"><!-- 激活组件扫描功能,在包cn.ysh.studio.spring.aop及其子包下面自动扫描通过注解配置的组件 --><context:component-scan base-package="cn.ysh.studio.spring.ao p"/><!-- 激活自动代理功能 --><aop:aspectj-autoproxy proxy-target-class="true"/><!-- 用户服务对象 --><bean id="userService"class="cn.ysh.studio.spring.aop.servic erService"/></beans>第二步是为Aspect切面类添加注解:package cn.ysh.studio.spring.aop.aspect;import mons.logging.Log;import mons.logging.LogFactory;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.annotation.After;import ng.annotation.AfterReturning;import ng.annotation.AfterThrowing;import ng.annotation.Around;import ng.annotation.Aspect;import ng.annotation.Before;import ng.annotation.Pointcut;import ponent;/*** 系统服务组件Aspect切面Bean* @author Shenghany* @date 2013-5-28*///声明这是一个组件@Component//声明这是一个切面Bean@Aspectpublic class ServiceAspect{private final static Log log =LogFactory.getLog(ServiceAspec t.class);//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点@Pointcut("execution(* cn.ysh.studio.spring.aop.service..* (..))")public void aspect(){}/** 配置前置通知,使用在方法aspect()上注册的切入点* 同时接受JoinPoint切入点对象,可以没有该参数*/@Before("aspect()")public void before(JoinPoint joinPoint){if(log.isInfoEnabled()){("before "+ joinPoint);}}//配置后置通知,使用在方法aspect()上注册的切入点@After("aspect()")public void after(JoinPoint joinPoint){if(log.isInfoEnabled()){("after "+ joinPoint);}}//配置环绕通知,使用在方法aspect()上注册的切入点@Around("aspect()")public void around(JoinPoint joinPoint){long start =System.currentTimeMillis();try{((ProceedingJoinPoint) joinPoint).proceed();long end =System.currentTimeMillis();if(log.isInfoEnabled()){("around "+ joinPoint +"\tUs e time : "+(end - start)+" ms!");}}catch(Throwable e){long end =System.currentTimeMillis();if(log.isInfoEnabled()){("around "+ joinPoint +"\tUs e time : "+(end - start)+" ms with exception : "+ e.getMessage ());}}}//配置后置返回通知,使用在方法aspect()上注册的切入点@AfterReturning("aspect()")public void afterReturn(JoinPoint joinPoint){if(log.isInfoEnabled()){("afterReturn "+ joinPoint);}}//配置抛出异常后通知,使用在方法aspect()上注册的切入点@AfterThrowing(pointcut="aspect()", throwing="ex")public void afterThrow(JoinPoint joinPoint,Exception ex){if(log.isInfoEnabled()){("afterThrow "+ joinPoint +"\t"+ ex. getMessage());}}}测试代码:package cn.ysh.studio.spring.aop;import mons.logging.Log;import mons.logging.LogFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationCon text;import erService;import er;/*** Spring AOP测试* @author Shenghany* @date 2013-5-28*/public class Tester{private final static Log log =LogFactory.getLog(Tester.clas s);public static void main(String[] args){//启动Spring容器ApplicationContext context =new ClassPathXmlApplicat ionContext("applicationContext.xml");//获取service组件UserService service =(UserService) context.getBean(" userService");//以普通的方式调用UserService对象的三个方法User user = service.get(1L);service.save(user);try{service.delete(1L);}catch(Exception e){if(log.isWarnEnabled()){log.warn("Delete user : "+ e.getMessa ge());}}}}控制台输出如下:INFO [spring.aop.aspect.ServiceAspect:40] before execution(User cn.y erService.get(long))INFO [erService:19] getUser method ...INFO [spring.aop.aspect.ServiceAspect:60] around execution(User cn.y erService.get(long))Use time :42 m s!INFO [spring.aop.aspect.ServiceAspect:48] after execution(User cn.ys erService.get(long))INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(User erService.get(long))INFO [spring.aop.aspect.ServiceAspect:40] before execution(void cn.y erService.save(User))INFO [erService:26] saveUser method ...INFO [spring.aop.aspect.ServiceAspect:60] around execution(void cn.y erService.save(User))Use time :2 ms!INFO [spring.aop.aspect.ServiceAspect:48] after execution(void cn.ys erService.save(User))INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(void erService.save(User))INFO [spring.aop.aspect.ServiceAspect:40] before execution(boolean c erService.delete(long))INFO [erService:32] delete method ...INFO [spring.aop.aspect.ServiceAspect:65] around execution(boolean c erService.delete(long))Use time :5 ms with exception : spring aop ThrowAdvice演示INFO [spring.aop.aspect.ServiceAspect:48] after execution(boolean cn. erService.delete(long))INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(bool ean erService.delete(long))WARN [studio.spring.aop.Tester:32]Delete user :Null return value f rom advice does not match primitive return type for: public boolean c erService.delete(long) throws java. lang.Exception可以看到,正如我们预期的那样,虽然我们并没有对UserSerivce类包括其调用方式做任何改变,但是Spring仍然拦截到了其中方法的调用,或许这正是AOP 的魔力所在。