SpringMVC之定义注解强势来袭!!!

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: SpringMVC之定义注解强势来袭!!!

一.原生注解

       Java注解是一种元数据,它提供了在Java代码中插入附加信息的方式。注解可以用于类、方法、变量、参数等的声明上,用于描述、标记或配置程序代码,而不改变代码的实际逻辑。

       Java注解使用@符号作为前缀,紧跟着注解名称,并可以包含一系列的参数。注解可以通过编译器处理或在运行时解析。

       1.1原生注解的分类

                      1.1 .1JDK基本注解:                                        

           @Override:用于标记方法覆盖了父类的方法。

           @Deprecated:用于标记方法、类或字段已经过时,不推荐使用。

           @SuppressWarnings:用于抑制编译器警告。

            ⭐⭐ 1.1.2JDK元注解 :  

                               @Retention:定义注解的保留策略
                                @Retention(RetentionPolicy.SOURCE) 注解仅存在于源码中,在                                                                            class字节码文件中不包含
                                @Retention(RetentionPolicy.CLASS)默认的保留策略,注解会在                                                                               class字节码文件中存在,但运行时无法获得,
                                @Retention(RetentionPolicy.RUNTIME)注解会在class字节码文件                                                                         中存在,在运行时可以通过反射获取到


                                @Target:指定被修饰的Annotation可以放置的位置(被修饰的目标)
                                @Target(ElementType.TYPE)                     接口、类
                                @Target(ElementType.FIELD)                     属性
                                @Target(ElementType.METHOD)                    方法
                                @Target(ElementType.PARAMETER)                 方法参数

                                       。。。。。


                              @Inherited:指定被修饰的Annotation将具有继承性

                               @Documented:指定被修饰的该Annotation可以被javadoc工具提取成文档.

                       1.1.3 自定义注解:

  1. 标记注解:没有成员变量的Annotation; 这种Annotation仅利用自身的存在与否来提供信息
  2. 元数据注解:包含成员变量的Annotation; 它们可以接受(和提供)更多的元数据;

       使用@interface关键字, 其定义过程与定义接口非常类似, 需要注意的是:

          Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的, 其方法名和返回值类型定义了该成员变量的名字和类型,而且我们还可以使用default关键字为这个成员变量设定默认值

二.注解的案例

      先来导入自定义注解的pom依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yinzi</groupId>
    <artifactId>spboottest01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spboottest01</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
<!--            <scope>test</scope>-->
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

        2.1 案例一(获取类与方法上的注解值)

               定义一个类:

package com.yinzi.annotation;
public enum  TranscationModel {
    Read, Write, ReadWrite;//定义三个实例,可以将它看作类
}

       写三个不同的注解:

/**
 * MyAnnotation1注解可以用在类、接口、属性、方法上
 * 注解运行期也保留
 * 不可继承
 */
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})//用在类、接口、属性、方法上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
    String name();
}
/**
 *  MyAnnotation2注解可以用在方法上
 *  注解运行期也保留
 *  不可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
    TranscationModel model() default TranscationModel.ReadWrite;
}
/**
 * MyAnnotation3注解可以用在方法上
 * 注解运行期也保留
 * 可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
    TranscationModel[] models() default TranscationModel.ReadWrite;
}

     第三步,创建几个方法使用这些注解

/**
 *
 * 获取类与方法上的注解值
 */
@MyAnnotation1(name = "abc")
public class Demo1 {
    @MyAnnotation1(name = "xyz")//获取这里的值
    private Integer age;
    @MyAnnotation2(model = TranscationModel.Read)
    public void list() {
        System.out.println("list");
    }
    @MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write})
    public void edit() {
        System.out.println("edit");
    }
}

               最后,进行测试

2.2  案例二(获取类属性上的注解属性值,默认值的赋予)

       自定义一个注解,并赋予默认值:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
    String value() default "默认value值";
    String what() default "这里是默认的what属性对应的值";
}

       建立类测试:

               有些两个值都赋予了,有些只赋予了一个

/**
 * 获取类属性上的注解属性值
 */
public class Demo2 {
    @TestAnnotation(value = "这就是value对应的值_msg1", what = "这就是what对应的值_msg1")
    private static String msg1;
    @TestAnnotation("这就是value对应的值1")//没有指定,默认value
    private static String msg2;
    @TestAnnotation(value = "这就是value对应的值2")
    private static String msg3;
    @TestAnnotation(what = "这就是what对应的值")
    private static String msg4;
}

       测试结果:

       2.3  案例三(获取参数修饰注解对应的属性值,非空注解)

               同样,先建立一个非空注解

/**
 * 非空注解:使用在方法的参数上,false表示此参数可以为空,true不能为空
 */
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {
    boolean value() default false;//默认为false
}

               建立方法,进行测试:

           测试


三.AOP结合自定义注解案例⭐⭐

       配置相关AOP  pom文件

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        applicationContext.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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--1. 注解式开发 -->
    <!-- 注解驱动 -->
    <context:annotation-config/>
    <!-- 用注解方式注入bean,并指定查找范围:com.javaxl.ssh2及子子孙孙包-->
    <context:component-scan base-package="com.yinzi"/>
    <!--开启动态代理-->
    <aop:aspectj-autoproxy />
</beans>

              定义一个标志日志的注解

package com.yinzi.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author yinzi
 * 日志注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    String desc();
}

       然后,我们创建一个切面类 LogAspect,用于实现日志记录的逻辑。

/**
 * @author yinzi
 */
@Component
@Aspect
public class MyLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);
    /**
     * 只要用到了com.javaxl.p2.annotation.springAop.MyLog这个注解的,就是目标类
     */
    @Pointcut("@annotation(com.yinzi.annotation.MyLog)")
    private void MyValid() {
    }
    @Before("MyValid()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        logger.debug("[" + signature.getName() + " : start.....]");
        System.out.println("[" + signature.getName() + " : start.....]");
        MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
        logger.debug("【目标对象方法被调用时候产生的日志,记录到日志表中】:"+myLog.desc());
        System.out.println("【目标对象方法被调用时候产生的日志,记录到日志表中】:" + myLog.desc());
    }
}

               在方法上运用日志注解

/**
 * @author yinzi
 */
@Controller
public class LogController {
    @RequestMapping("/mylog")
    @MyLog(desc = "这是结合spring aop知识,讲解自定义注解应用的一个案例")
    public void testLogAspect(){
        System.out.println("这里随便来点啥");
    }
}

       运行结果: 这只是大概的模拟了一下

               好啦,今天的分享就到这啦!!

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
6月前
|
XML Java 数据格式
注解之光:揭秘Spring注解发展的演进历程
注解之光:揭秘Spring注解发展的演进历程
48 0
注解之光:揭秘Spring注解发展的演进历程
|
6月前
|
Java Spring
切面编程的锋芒:Spring切入点的玩法与技巧
切面编程的锋芒:Spring切入点的玩法与技巧
44 0
切面编程的锋芒:Spring切入点的玩法与技巧
|
6月前
|
JSON 前端开发 Java
历经14天自定义3个注解解决项目的3个Swagger难题
历经14天自定义3个注解解决项目的3个Swagger难题
160 0
SpringBoot中的内容协商,颠覆你的认知
本文将介绍 SpringMVC 中内容协商,可能有朋友听过,没听过的估计觉得很陌生,不管怎么样,先告诉你一点,这篇是非常重要的一个知识点,一定不要错误,坚持看完,一定会有大量收获,
|
监控 前端开发 Java
SpringMvc第五战-【SpringMvcJSR303和拦截器】
SpringMvc第五战-【SpringMvcJSR303和拦截器】
|
JSON 安全 前端开发
SpringMvc决战-【SpringMVC之自定义注解】
SpringMvc决战-【SpringMVC之自定义注解】
|
XML Java 数据格式
学习SpringMvc第三战-利用SpringMvc实现CRUD
学习SpringMvc第三战-利用SpringMvc实现CRUD
|
XML 设计模式 JSON
解密SpringMVC:探秘常用注解,让你的Java应用飞速起航!
解密SpringMVC:探秘常用注解,让你的Java应用飞速起航!
|
前端开发 Java 索引
40 个 SpringBoot 常用注解:让生产力爆表! 1
40 个 SpringBoot 常用注解:让生产力爆表!
|
Java Spring 容器
40 个 SpringBoot 常用注解:让生产力爆表! 2
40 个 SpringBoot 常用注解:让生产力爆表!