一个简单的例子,学习自定义注解和AOP

转载自   一个简单的例子,学习自定义注解和AOP

记得今年年初刚开始面试的时候,被问的最多的就是你知道Spring的两大核心嘛?那你说说什么是AOP,什么是IOC?我相信你可能也被问了很多次了。

 

1、到底是什么是AOP?

所谓AOP也就是面向切面编程,能够让我们在不影响原有业务功能的前提下,横切扩展新的功能。这里面有一个比较显眼的词我们需要注意一下,横切,它是基于横切面对程序进行扩展的。

 

2、AOP相关术语

在Spring的AOP中有很多的术语,而且容易混淆,大家一定要先搞清楚这几个概念:

  • 连接点(Joinpoint):在程序执行过程中某个特定的点,比如类初始化前、类初始化后,方法调用前,方法调用后;

  • 切点(Pointcut:所谓切点就是你所切取的类中的方法,比如你横切的这个类中有两个方法,那么这两个方法都是连接点,对这两个方法的定位就称之为切点;

  • 增强(Advice:增强是织入到连接点上的一段程序,另外它还拥有连接点的相关信息;

  • 目标对象(Target):增强逻辑的织入目标类,就是我的增强逻辑植入到什么位置;

  • 引介(Introduction:一种特殊的增强,它可以为类添加一些属性喝方法;

  • 织入(Weaving:织入就是讲增强逻辑添加到目标对象的过程;

  • 代理(Proxy:一个类被AOP织入增强后,就会产生一个结果类,他是融合了原类和增强逻辑的代理类;

  • 切面(Aspect:切面由切点和增强组成,他是横切逻辑定义和连接点定义的组成;

 

3、AOP功能实践

我们这里主要是学习SpringBoot中的一些功能,所以我们这里用的是SpringBoot工程,版本也是最新的2.0.5版本。

创建SpringBoot工程就不说了,我们直接引入Maven的依赖:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency><!-- 引入AOP --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.6.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.20</version><configuration><skip>true</skip></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions></executions></plugin></plugins></build>

首先我们来创建一个Controller类:

@RestController
public class LoginController {@GetMapping(value = "/username")public String getLoginUserName(String userName, Integer age) {return userName + " --- " + age;}
}

创建切面:

@Aspect
@Component
public class LogAspect {/*** 功能描述: 拦截对这个包下所有方法的访问** @param:[]* @return:void**/@Pointcut("execution(* com.example.springbootaop.controller.*.*(..))")public void loginLog() {}// 前置通知@Before("loginLog()")public void loginBefore(JoinPoint joinPoint) {// 我们从请求的上下文中获取request,记录请求的内容ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();System.out.println("请求路径 : " + request.getRequestURL());System.out.println("请求方式 : " + request.getMethod());System.out.println("方法名 : " + joinPoint.getSignature().getName());System.out.println("类路径 : " + joinPoint.getSignature().getDeclaringTypeName());System.out.println("参数 : " + Arrays.toString(joinPoint.getArgs()));}@AfterReturning(returning = "object", pointcut = "loginLog()")public void doAfterReturning(Object object) {System.out.println("方法的返回值 : " + object);}// 方法发生异常时执行该方法@AfterThrowing(throwing = "e",pointcut = "loginLog()")public void throwsExecute(JoinPoint joinPoint, Exception e) {System.err.println("方法执行异常 : " + e.getMessage());}// 后置通知@After("loginLog()")public void afterInform() {System.out.println("后置通知结束");}// 环绕通知@Around("loginLog()")public Object surroundInform(ProceedingJoinPoint proceedingJoinPoint) {System.out.println("环绕通知开始...");try {Object o =  proceedingJoinPoint.proceed();System.out.println("方法环绕proceed,结果是 :" + o);return o;} catch (Throwable e) {e.printStackTrace();return null;}}
}

注解概述:

  • @Apsect:将当前类标识为一个切面;

  • @Pointcut:定义切点,这里使用的是条件表达式;

  • @Before:前置增强,就是在目标方法执行之前执行;

  • @AfterReturning:后置增强,方法退出时执行;

  • @AfterThrowing:有异常时该方法执行;

  • @After:最终增强,无论什么情况都会执行;

  • @Afround:环绕增强;

 

测试:

异常测试:

 

4、定义自定义注解

应用场景:在我之前上个项目的时候,有这样一个注解,就是在访问其他接口的时候必须要登录,那么这个时候我们就定义一个注解,让它去对用户是否登录进行校验,那么基于这样的一个场景,我们来定义一个校验登录的注解。

创建一个注解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {String desc() default "验证是否登录";
}

创建一个AOP切面:

@Aspect
@Component
public class LoginAspect {@Pointcut(value = "@annotation(com.example.springbootaop.annotation.Auth)")public void access() {}@Before("access()")public void before() {System.out.println("开始验证用户是否登录...");}@Around("@annotation(auth)")public Object around(ProceedingJoinPoint pj, Auth auth) {// 获取注解中的值System.out.println("注解中的值 : " + auth.desc());try {// 检验是否登录 true 已经登录  false 未登录Boolean flag = false;if (flag == true) {return "登录成功";} else {return "未登录";}} catch (Throwable throwable) {return null;}}
}

测试未登录:

测试登录:

这样我们就可以简单的实现了一个登录校验的注解。

通过今天的分享你会使用AOP和自定义注解了吗?我把源码的地址放在下面,有兴趣的朋友可以看看。

https://github.com/liangbintao/SpringBootIntegration.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Xamarin for iOS 11(一) - 初尝ARKit

编者语&#xff1a;Xamarin 的兼容性是它最大的优点&#xff0c;对于iOS / Android 新的功能支持也是无缝的&#xff0c;做到100%兼容。Xamarin.ios for iOS 11.0的支持已经开始&#xff0c;大家可以在这里下载最新的Preview支持 (https://releases.xamarin.com/preview-xcode-…

挺不喜欢下雪的

你要储蓄你的可爱&#xff0c;眷顾你的善良&#xff0c;变得勇敢。当这个世界越来越坏时&#xff0c;只希望你能越来越好。——《南山南》昨天夜间&#xff0c;窗外雪花飘飘&#xff0c;朋友圈中到处都是晒下雪的照片&#xff0c;有的说是“这是2020年的第一场雪”&#xff0c;…

是什么使你留在你的公司

一个故事 之前离职的一个同事&#xff0c;是典型的技术型人才&#xff0c;前段时间跟他一起吃饭&#xff0c;得知他工作状况不是很理想&#xff08;他在创业型团队&#xff0c;工作强度非常大&#xff0c;且做出来的东西得不到应有的认可&#xff0c;公司给他的报酬也不是很高…

有些事,父母一定不能依着孩子!

今天的文章&#xff0c;可能有的人不太喜欢。在我教学这么些年以来&#xff0c;这个问题在今年出现的最多——父母总是站在孩子的角度&#xff0c;不管什么事都是依着孩子&#xff1b;如果此事对孩子好也就罢辽&#xff0c;但是明明对孩子没有一点好处&#xff0c;还要和孩子一…

“看起来你每天都要做好多事,你有时间吗?”

“我看你每天要干的事好多啊,你有那么多时间吗?” “有啊,早起会儿,晚睡会儿,时间就出来了” 我每天确实是要做好多事。 01 我是一个喜欢规律生活的人,通常会将自己的一天划分为好多块,每一块时间安排的事都不一样,不太喜欢别人打乱我的生活规律,也不知道这是好事还是…

Sentinel限流保护

自定义限流错误页

浅谈 EF CORE 迁移和实例化的几种方式

出于学习和测试的简单需要&#xff0c;使用 Console 来作为 EF CORE 的承载程序是最合适不过的。今天笔者就将平时的几种使用方式总结成文&#xff0c;以供参考&#xff0c;同时也是给本人一个温故知新的机会。因为没有一个完整的脉络&#xff0c;所以也只是想起什么写点什么&a…

Redis 高可用特性之 “持久化” 详解

转载自 Redis 高可用特性之 “持久化” 详解 在之前的文章中&#xff0c;介绍了《Redis的内存模型》&#xff0c;从这篇文章开始&#xff0c;将依次介绍 Redis 高可用相关的知识——持久化、复制(及读写分离)、哨兵、以及集群。 本文将先说明上述几种技术分别解决了 Redis 高…

这本书强烈推荐看看!

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】今天&#xff0c;给大家推荐一本书《计算机是怎样跑起来的》&#xff0c;作者&#xff1a;矢泽久雄。也不知道它是怎么进入我的书架的&#xff0c;由于最近一直在看理财类的书籍&#xff0c;所以以前加入…

基于.NET CORE微服务框架 -谈谈Cache中间件和缓存降级

1、前言 surging受到不少.net同学的青睐&#xff0c;也提了不少问题&#xff0c;提的最多的是什么时候集成API 网关&#xff0c;在这里回答大家最近已经开始着手研发&#xff0c;应该在1,2个月内会有个初版API网关&#xff0c;其它像Token身份验证&#xff0c;限流降级等功能完…

1 分钟教会你用 Spring Boot 发邮件

转载自 1 分钟教会你用 Spring Boot 发邮件 Spring Boot 提供了一个发送邮件的简单抽象&#xff0c;使用的是下面这个接口。 org.springframework.mail.javamail.JavaMailSender Spring Boot 提供了一个 starter&#xff0c;并能自动配置&#xff0c;下面来做个小例子&#xf…

小二,先来两桂花豆沙包!

“包子嘞&#xff0c;卖包子嘞&#xff0c;新出锅的大包子&#xff0c;走过路过千万不要错过呦~包子嘞……”某年某月某下午&#xff0c;百万包子铺进来一人&#xff0c;进来便招呼&#xff1a;“小二&#xff0c;包子怎么卖&#xff1f;”小二&#xff1a;“客官&#xff0c;你…

SQL Server 2017 RC1 现已实现 Linux 功能扩展

经过七个预览版本的迭代之后&#xff0c;Microsoft 宣告发布第一个 SQL Server 2017 候选版本。开发人员可以藉由该版本来探索一些扩展 SQL Server Linux 版能力的新改进。 在这些新改进中&#xff0c;首先是对 Linux 上SQL Server 的 Active Directory 身份验证的支持。使用 …

一百馒头一百僧,大僧三个更无争,小僧三人分一个大小和尚得几丁?

如题&#xff1a;一百馒头一百僧&#xff0c;大僧三个更无争&#xff0c;小僧三人分一个大小和尚得几丁&#xff1f; 要求使用java实现求得大僧小僧各有多少人&#xff1f; public class shdjshj {public static void main(String[] args) {for(int i 1;i<100;i){int j 1…

Microsoft使用.NET Core SDK遥测数据

Microsoft发布了采集自.NET Core SDK用户的遥测原始数据集。数据集的时间跨度是从2016年第三季度到2017年第二季度&#xff0c;为了解当前开发人员使用SDK的情况提供了一个视角。据Microsoft的Rich Lander介绍&#xff0c;今后Microsoft将每季度提供一次遥测数据集&#xff0c;…

你们好好的学,回头教教我~

辣椒酱中奖的已经安排发货了&#xff0c;不日即可达到&#xff0c;注意收货。雄雄辣椒酱&#xff0c;免费送~这一周&#xff0c;3班的孩子们都在培训双创的内容&#xff0c;因为这个培训是学校统一组织的&#xff0c;所以对培训的内容以及培训方式我是一无所知的。周二我值班&a…