spring ioc注解SpringBoot系列之使⽤⾃定义注解校验⽤户是否登录
记得今年年初刚开始⾯试的时候,被问的最多的就是你知道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>
&porting.outputEncoding>UTF-8</porting.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(* ller.*.*(..))")
public void loginLog() {
}
/
/ 前置通知
@Before("loginLog()")
public void loginBefore(JoinPoint joinPoint) {
// 我们从请求的上下⽂中获取request,记录请求的内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestAttributes();      HttpServletRequest request = Request();
System.out.println("请求路径 : " + RequestURL());
System.out.println("请求⽅式 : " + Method());
System.out.println("⽅法名 : " + Signature().getName());
System.out.println("类路径 : " + Signature().getDeclaringTypeName());
System.out.println("参数 : " + Args()));
}
@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) {
}
// 后置通知
@After("loginLog()")
public void afterInform() {
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:定义切点,这⾥使⽤的是条件表达式;
:前置增强,就是在⽬标⽅法执⾏之前执⾏;
@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 = "@ample.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;
}
}
}
测试未登录:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。