首页 > 其他分享 >注解的本质与工作原理

注解的本质与工作原理

时间:2024-09-25 13:13:04浏览次数:1  
标签:Autowired Spring Component 本质 原理 注解 ElementType public

一、注解的本质是什么?

1.1 注解的定义

注解(Annotation)是Java 5引入的一种元数据(Metadata)机制,用于在代码中添加额外的信息。注解本质上是一种特殊的接口,后续会由工具和框架在编译时、类加载时、或运行时进行处理,以实现特定的功能。

1.2 注解的分类

注解可以分为三类:

  1. 标准注解:Java标准库提供的注解,如@Override、@Deprecated、@SuppressWarnings等。
  2. 元注解:用于注解其他注解的注解,如@Retention、@Target、@Inherited、@Documented等。
  3. 自定义注解:用户自定义的注解,用于特定的应用场景。

1.3 注解的本质

注解本质上是Java中的一种接口。每个注解都会自动继承java.lang.annotation.Annotation接口。当我们在代码中使用注解时,编译器会在编译后的字节码中生成相应的注解信息,这些信息可以在运行时通过反射机制获取并处理。

例如,定义一个简单的注解:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    String value();
}

编译后的字节码中会包含MyAnnotation注解的信息,我们可以通过反射机制获取并处理这些信息。

1.4 注解的处理

注解的处理方式主要有三种:

  1. 编译时处理:通过注解处理器(Annotation Processor)在编译时处理注解,生成额外的代码或资源文件。

  2. 类加载时处理:通过字节码增强技术(如ASM、Javassist)在类加载时处理注解,修改字节码。

  3. 运行时处理:通过反射机制在运行时处理注解,实现特定的功能。

二、为何注解能够完成特定功能?

2.1 注解的运行机制

当我们在代码中使用注解时,编译器会将注解信息存储在字节码中。在运行时,框架(如Spring)通过反射机制获取注解信息,并根据注解的定义执行相应的逻辑。

例如,Spring中的@Autowired注解用于依赖注入。当Spring容器初始化时,会扫描所有的Bean,通过反射机制查找标注了@Autowired的字段或方法,并注入相应的依赖对象。

2.2 Spring注解的工作原理

Spring框架通过多种机制处理注解,包括类路径扫描、反射和动态代理等。以下是几个常用Spring注解的工作原理:

  1. @Component:用于标注一个类为Spring Bean。Spring在初始化时会扫描指定的包,将标注了@Component的类注册为Bean。

  2. @Autowired:用于自动注入依赖对象。Spring容器在创建Bean时,通过反射查找标注了@Autowired的字段或方法,并注入相应的依赖对象。

  3. @Transactional:用于声明事务。Spring AOP(面向切面编程)在运行时通过动态代理或字节码增强技术,为标注了@Transactional的方法生成代理类,实现事务管理。

2.3 Spring注解处理的核心类

Spring框架中有几个核心类负责处理注解:

  1. AnnotationConfigApplicationContext:一个基于注解配置的Spring应用上下文,实现了注解的扫描和处理。

  2. ClassPathBeanDefinitionScanner:用于扫描指定包路径下的类,并根据注解信息生成Bean定义。

  3. AutowiredAnnotationBeanPostProcessor:一个Bean后置处理器,用于处理@Autowired注解,实现依赖注入。

  4. TransactionAspectSupport:用于处理@Transactional注解,实现事务管理。

2.4 示例:@Component和@Autowired的处理流程

以下是@Component和@Autowired注解在Spring中的处理流程:

1、@Component的处理流程:

  • Spring容器启动时,AnnotationConfigApplicationContext会初始化ClassPathBeanDefinitionScanner。

  • ClassPathBeanDefinitionScanner扫描指定包路径下的类,查找标注了@Component的类。

  • 对于每个标注了@Component的类,生成相应的Bean定义,并注册到Spring容器中。

2、@Autowired的处理流程:

  • Spring容器在创建Bean时,会初始化AutowiredAnnotationBeanPostProcessor。
  • AutowiredAnnotationBeanPostProcessor通过反射查找所有Bean中标注了@Autowired的字段和方法。
  • 对于每个标注了@Autowired的字段和方法,从Spring容器中查找相应的依赖对象,并注入到目标Bean中。

2.5 实例代码

以下是一个简单的实例代码,展示@Component@Autowired注解的使用及其处理流程:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

// 定义一个Service类,标注为Spring Bean
@Component
public class MyService {
    public void serve() {
        System.out.println("Service is serving...");
    }
}

// 定义一个Controller类,依赖于Service类
@Component
public class MyController {
    private final MyService myService;

    @Autowired
    public MyController(MyService myService) {
        this.myService = myService;
    }

    public void process() {
        myService.serve();
    }
}

// 配置类,启用组件扫描
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

// 测试类
public class Main {
    public static void main(String[] args) {
        // 初始化Spring容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // 获取Controller Bean并调用其方法
        MyController controller = context.getBean(MyController.class);
        controller.process();

        // 关闭Spring容器
        context.close();
    }
}

上述代码中,Spring容器启动时会扫描com.example包路径下的所有类,找到标注了@Component的MyService和MyController类,并将它们注册为Bean。随后,通过@Autowired注解,Spring容器会自动注入MyService实例到MyController中,完成依赖注入

三、元注解是什么?

3.1 元注解的定义

元注解是用于注解其他注解的注解。元注解为注解提供了配置元数据,使得注解本身可以携带更多的信息,控制其作用范围和生命周期。

3.2 常见的元注解

Java标准库提供了几个常见的元注解,包括:

  1. @Retention:指定注解的保留策略,即注解在什么阶段可见。取值范围包括:

    • RetentionPolicy.SOURCE:注解仅在源码中保留,编译时会被丢弃。

    • RetentionPolicy.CLASS:注解在编译时保留,但不会被加载到JVM中(默认值)。

    • RetentionPolicy.RUNTIME:注解在运行时保留,可以通过反射机制读取。

  2. @Target:指定注解可以应用的程序元素。取值范围包括:

    • ElementType.TYPE:类、接口或枚举。

    • ElementType.FIELD:字段。

    • ElementType.METHOD:方法。

    • ElementType.PARAMETER:方法参数。

    • ElementType.CONSTRUCTOR:构造函数。

    • ElementType.LOCAL_VARIABLE:局部变量。

    • ElementType.ANNOTATION_TYPE:注解类型。

    • ElementType.PACKAGE:包。

  3. @Inherited:指定注解可以被子类继承。

  4. @Documented:指定注解将包含在Javadoc中。

3.3 示例:自定义注解及元注解的使用

以下是一个示例代码,展示如何自定义注解

并使用元注解:

import java.lang.annotation.*;

// 定义一个自定义注解,使用元注解进行配置
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface MyCustomAnnotation {
    String value() default "default";
}

// 使用自定义注解
public class Example {
    @MyCustomAnnotation(value = "example")
    public void myMethod() {
        // 方法实现
    }
}

// 解析自定义注解
import java.lang.reflect.Method;

public class AnnotationProcessor {
    public static void main(String[] args) throws Exception {
        Method method = Example.class.getMethod("myMethod");
        if (method.isAnnotationPresent(MyCustomAnnotation.class)) {
            MyCustomAnnotation annotation = method.getAnnotation(MyCustomAnnotation.class);
            System.out.println("Annotation value: " + annotation.value());
        }
    }
}

在上述代码中,定义了一个自定义注解MyCustomAnnotation,并使用元注解@Retention、@Target和@Documented对其进行配置。通过反射机制,可以在运行时解析该注解并获取注解信息。

四、Spring注解源码解析

4.1 @Component注解源码解析

@Component注解是Spring框架中最基本的注解,用于将一个类标识为Spring Bean。以下是@Component注解的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
    String value() default "";
}

@Component注解本身使用了三个元注解:@Target、@Retention和@Documented。其中,@Target(ElementType.TYPE)表示@Component注解可以应用于类、接口或枚举;@Retention(RetentionPolicy.RUNTIME)表示@Component注解在运行时可见;@Documented表示@Component注解将包含在Javadoc中。

4.2 @Autowired注解源码解析

@Autowired注解用于自动注入依赖对象。以下是@Autowired注解的源码:

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

@Autowired注解使用了@Target、@Retention和@Documented元注解。其中,@Target元注解指定@Autowired可以应用于构造函数、字段、方法和注解类型;@Retention(RetentionPolicy.RUNTIME)表示@Autowired注解在运行时可见;@Documented表示@Autowired注解将包含在Javadoc中。

4.3 @Transactional注解源码解析

@Transactional注解用于声明事务。以下是@Transactional注解的源码:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    String value() default "";
    // 其他属性省略
}

@Transactional注解使用了@Target、@Retention、@Inherited和@Documented元注解。其中,@Target元注解指定@Transactional可以应用于方法和类;@Retention(RetentionPolicy.RUNTIME)表示@Transactional注解在运行时可见;@Inherited表示@Transactional注解可以被子类继承;@Documented表示@Transactional注解将包含在Javadoc中。

标签:Autowired,Spring,Component,本质,原理,注解,ElementType,public
From: https://www.cnblogs.com/clswhde/p/18431138

相关文章

  • 【SpringBoot】@Valid @Validated 注解校验时机实现原理
    1 前言上节我们看了【SpringBoot】@Validated@Valid参数校验概述以及使用方式,对于@Valid以及@Validated有了大概的认识,并也尝试了集中校验方式,那么本节我们重点看一下SpringBoot中@Valid@Validated的校验实现原理。2 准备工作客户类我还是用上节的那个类,然后我......
  • 【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、
    文章目录【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、Volatile关键字、JMM、重排序、双重检验锁)1.Volatile的特性2.Volatile的用法3.CPU多核硬件架构剖析4.JMM内存模型4.1主要特性4.2JMM的工作原理4.3实现机制5.JMM八......
  • 【JUC并发编程系列】深入理解Java并发机制:线程局部变量的奥秘与最佳实践(五、ThreadLo
    文章目录【JUC并发编程系列】深入理解Java并发机制:线程局部变量的奥秘与最佳实践(五、ThreadLocal原理、对象之间的引用)1.基本API介绍2.简单用法3.应用场景4.Threadlocal与Synchronized区别5.内存溢出和内存泄漏5.2内存溢出(MemoryOverflow)5.2内存泄漏(Mem......
  • cameralink卡设计原理图:287-基于FMC接口的1路Base cameralink输入1路Base cameralink
    基于FMC接口的1路Basecameralink输入1路Basecameralink输出子卡  一、板卡概述      该板卡是我公司自主研发的1路Basecameralink输入,1路Basecameralink输出的FMC子卡,LPC-FMC连接器。FMC连接器是一种高速多pin的互连器件,广泛应用于板卡对接的设......
  • ❗Vue原理 (必考!)
    1.组件化基础如何理解MVVM?-----很久以前就有组件化,数据驱动视图(MVVM,setState)Vue、React框架的出现,使得我们可以直接去操控数据而不是原始的DOM节点。View:视图DOMModel:VUE组件里的data或者Vuex里state里面的数据。两者之间通过ViewModel相关联,使得我们在Model修改的......
  • AI大模型知识点梳理:大模型是什么?大模型发展历程、底层原理、优点和不足、如何学习大模
    一、AI大模型是什么AI大模型是指具有巨大参数量的深度学习模型,通常包含数十亿甚至数万亿个参数。这些模型可以通过学习大量的数据来提高预测能力,从而在自然语言处理、计算机视觉、自主驾驶等领域取得重要突破。AI大模型的定义具体可以根据参数规模来分类。根据OpenAI的分类方法,可以......
  • CDN 底层原理
    背景笔者在近期秋招面试中,遇到了一位比较资深的开发者,他问的就相对于前面几轮面试更偏底层一些,其中聊到了CDN的底层原理,就这个问题讨论了很久。面试官:“你知道CDN的是怎么知道找到距离你最近的服务器,然后把资源分配给你的吗?”其实我在这个时候不太清楚,就凭印象想了一下之前学的......
  • 在多态的方法调用中为什么会出现“左边编译左边运行”的现象?多态创建的对象到底是谁属
    目录“左边编译左边运行”的两个原因:什么是“编译看左边,运行看右边”?为什么会出现“左边编译左边运行”现象?1.子类没有重写父类的方法2.重载与重写的混淆(重难点)问题:编译器是怎么看一个方法是重写还是重载的呢?区分方式:查看方法的签名如何避免“左边编译左边运行”的......
  • Cache(高速缓冲存储器)的基本概念和原理
    目录一、Cache基本概述1.Cache :2.局部性原理二、Cache性能分析:一、Cache基本概述CPU的读取指令速度很快,主存的速度很慢,如果快速的CPU每一次都从主存读取数据,会被主存拖累,降低执行效率。Cache:解决主存和CPU速度不匹配问题 1.Cache :   Cache会将CPU经常访问......
  • @Scheduled注解停止定时任务、@Scheduled设置定时任务不启用、springboot 配置Schedul
    文章目录一、关闭定时任务1.1、方法一:注释@EnableScheduling注解1.1.1、原理1.2、方法二:不加载ScheduledAnnotationBeanPostProcessor类1.3、方法三:注释@Scheduled注解1.4、方法四:设置@Scheduled注解cron时间不开启(推荐)1.4.1、原理在项目中我们可能会遇到这样一......