springboot注解及原理详解

一、注解

1、@SpringBootApplication

这个注解是Spring Boot最核心的注解,用在 Spring Boot的主类上,标识这是一个 Spring Boot 应用,用来开启 Spring Boot 的各项能力。实际上这个注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三个注解的组合。由于这些注解一般都是一起使用,所以Spring Boot提供了一个统一的注解@SpringBootApplication。

2、@Controller

在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面
若返回json等内容到页面,则需要再加上@ResponseBody注解

3、@ResponseBody

表示该方法的返回结果直接写入HTTP response body中。
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。

4、@RestController

用于标注控制层组件(如struts中的action),表示这是个控制器bean,并且是将函数的返回值直 接填入HTTP响应体中,是REST风格的控制器;它是@Controller和@ResponseBody的合集

5、@ComponentScan

组件扫描。让spring Boot扫描到Configuration类并把它加入到程序上下文。
@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。

6、@Repository

@Repository 是 Spring 的注解,用于声明一个 Bean。@Repository单独使用没用。可以这样理解,注解放在接口上本来就没有意义,spring中在mapper接口上写一个@Repository注解,只是为了标识,要想真正是这个接口被扫描,必须使用@MapperScannerConfigurer

eg:
<!-- 配置 Mapper 扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="com.shenlei.mapper"/>
</bean>
这段配置会扫描com.shenlei.mapper包下所有的接口,然后创建各自的动态代理类。

7、@Mapper

@Mapper是mybatis自身带的注解。在spring程序中,mybatis需要找到对应的mapper,在编译时生成动态代理类,与数据库进行交互,这时需要用到@Mapper注解
但是有时候当我们有很多mapper接口时,就需要写很多@Mappe注解,这样很麻烦,有一种简便的配置化方法便是在启动类上使用@MapperScan注解,这样可以自动扫描包路径下所有的mapper接口,从而不用再在接口上添加任何注解。
相同点:
@Mapper和@Repository都是作用在dao层接口,使得其生成代理对象bean,交给spring 容器管理

不同点:
1、@Mapper不需要配置扫描地址,可以单独使用,如果有多个mapper文件的话,可以在项目启动类中加入@MapperScan(“mapper文件所在包”)
2、@Repository不可以单独使用,否则会报错误,要想用,必须配置扫描地址(@MapperScannerConfigurer)

8、@Service

一般用于修饰service层的组件

9、@Component

泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

10、@Bean

相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
详细介绍:https://blog.csdn.net/weixin_42140261/article/details/104864333

11、@AutoWired

byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
当加上(required=false)时,就算找不到bean也不报错。

12、@Qualifier

当有多个同一类型的Bean时,可以用@Qualifier("name")来指定。与@Autowired配合使用

13、@Resource(name=“name”,type=“type”)

没有括号内内容的话,默认byName。与@Autowired干类似的事。

14、@PathVariable

路径变量。参数与大括号里的名字一样要相同
例如:
@GetMapping("sendMessage/{message}")
public void sendMessage(@PathVariable String message){
	// do others
}

15、@Param

mybatis框架中给SQL语句中的参数赋值的
eg:
mapper中的方法:
public User selectUser(@Param("userName") String name,@Param("password") String pwd);
映射到xml中的<select>标签:
<select id="selectUser" resultMap="User">  
   select * from user  where user_name = #{userName} and user_password=#{password}  
</select>
其中where user_name = #{userName} and user_password = #{password}中的userName和password都是从注解@Param()里面取出来的,取出来的值就是方法中形式参数 String name 和 String pwd的值。

16、@RequestParam

用于将指定的请求参数赋值给方法中的形参
有三个属性:
  (1)value:请求参数名(必须配置)
  (2)required:是否必需,默认为 true,即 请求中必须包含该参数,如果没有包含,将会抛出异常(可选配置)
  (3)defaultValue:默认值,如果设置了该值,required 将自动设为 false,无论你是否配置了required,配置了什么值,都是 false(可选配置)

举例:

1.为演示效果,首先需要创建一个测试控制类,然后创建一个测试方法,如图所示,方法里添加一个参数,此时方法参数没有添加注解

在这里插入图片描述

2.通过idea工具启动web项目,然后通过浏览器访问测试效果,不带参数则获取的参数为null,但页面可以正常显示,请求可以正常的执行。

在这里插入图片描述

带上参数之后,参数可以正常的获取并打印出来了

在这里插入图片描述

3.下面来对比下添加注解的效果,但只是添加@RequestParam,没有带任何的注解设置参数。

在这里插入图片描述

4.再次通过浏览器访问查看效果,此时带上userName参数页面可以正常显示并打印出结果值,但如图所示,不带参数的时候,页面报错,返回400,并提示userName不存在

在这里插入图片描述

在这里插入图片描述

5.当然这样的限制是可以选择的,@RequestParam里添加required=false来关闭必须参数的限制,这样就和第一种不带注解的效果一样了

在这里插入图片描述

在这里插入图片描述

6.@RequestParam还可以在参数为空的情况下,为我们设置一个参数的默认值,如图所示,可以看出来,没有参数的情况下,获取到的就是默认值

在这里插入图片描述

在这里插入图片描述

7.默认参数的key名称是方法里的参数名称,但通过@RequestParam可以自定义另外一个,因为在某些条件下,方法名称固定下来不可以修改了,但请求的参数又需要通过另外一个参数key名称来传递,这样就可以通过这样的方式来实现

在这里插入图片描述

在这里插入图片描述

17、@PostConstruct

该注解是Java jdk提供的注解,而不是Spring框架提供的, JavaEE5引入了@PostConstruct和@PreDestroy两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作。
该注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的初始化方法)

18、@Configuration

Configuration注释类表明其主要目的是作为bean定义的源;@Configuration类允许通过调用同一类中的其他@Bean方法来定义bean之间的依赖关系

19、@Import

@Import({User.class, DBHelper.class})给容器中自动创建出这两个类型的组件、默认组件的名字就是 全类名

20、@Conditional

条件装配:满足Conditional指定的条件,则进行组件注入

在这里插入图片描述

用@ConditionalOnMissingBean举例说明
@ConditionalOnMissingBean(name = "tom")//没有tom名字的Bean时,MyConfig类的Bean 才能生效。

21、@ImportResource

@ImportResource注解用于导入Spring的配置文件,让配置文件里面的内容生效
例如:
@ImportResource(locations = "classpath:applicationContext.xml")
@SpringBootApplication
public class Project50RabbitmqFinalApplication {
    public static void main(String[] args) {
        SpringApplication.run(Project50RabbitmqFinalApplication.class, args);
    }
}

22、@ConfigurationProperties

Spring Boot提供了基于类型安全的配置方式,通过@ConfigurationProperties将properties属性和一个Bean关联,从而实现类型安全的配置。

第一种方式:
1.
@Component
@ConfigurationProperties(prefix = "book01")
public class Book {
    private String name;
    private String author;
    private int age;
 
    //get.. set..
    }
2.    
application.properties文件下配置
book01.name="java实战"
book01.author="李四"
book01.age=12

第二种方式:
1.
@EnableConfigurationProperties({com.example.pojo.Book.class})
@Configuration
public class Myconfig {
    @Autowired
    private Book book;
  	 .....
}
2.
@ConfigurationProperties(prefix = "book02")
public class Book {
    private String name;
    private String author;
    private int age;
 
    //get.. set..
    }
3.
application.properties文件下配置
book02.name="java实战"
book02.author="李四"
book02.age=12

二、插件

1、快速打包

Spring Boot 在 Maven 是通过引入 spring-boot-maven-plugin 插件来构建可执行 Jar 包的
eg:
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

在IDEA的Maven插件上点击运行 clean 、package,把helloworld工程项目的打包成jar包, 
打包好的jar包被生成在helloworld工程项目的target文件夹内。 
用cmd运行java -jar boot-01-helloworld-1.0-SNAPSHOT.jar,既可以运行helloworld工程项目。
将jar包直接在目标服务器执行即可。

三、依赖管理原理

1、父项目做依赖管理

springboot项目依赖于其父项目,如下:
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.6</version>
    <!-- lookup parent from repository:指定了relativePath,
    但值是空的,设定一个空值将始终从仓库中获取,不从本地路径获取. -->
    <relativePath/> 
</parent>

此项目又依赖于
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>3.1.6</version>
</parent>

其内部规定了一系列的版本号,如下:
<properties>
    <activemq.version>5.18.3</activemq.version>
    <angus-mail.version>1.1.0</angus-mail.version>
    <artemis.version>2.28.0</artemis.version>
    <aspectj.version>1.9.20.1</aspectj.version>
    <assertj.version>3.24.2</assertj.version>
    <awaitility.version>4.2.0</awaitility.version>
    <brave.version>5.15.1</brave.version>
    .......
</properties>
它几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制

2、自动版本仲裁

引入依赖默认都可以不写版本 
引入非版本仲裁的jar,要写版本号。

3、修改默认版本号

1. 查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。 
2. 在当前项目里面重写配置,如下面的代码。
<properties> 
	<mysql.version>5.1.43</mysql.version>
</properties>

4、starter场景启动器

starter场景启动器:spring-boot-starter-*   (*表示某种场景)
例如:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
里面自动导入了这个场景的所有常规需要的依赖
eg:
<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>3.1.6</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>3.1.6</version>
      <scope>compile</scope>
    </dependency>
    .......
</dependencies>    
而所有场景启动器最底层的依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>3.1.6</version>
    <scope>compile</scope>
</dependency>

*-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.16</version>
</dependency>

四、自动配置原理

1、默认的包结构

主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来 
无需以前的包扫描配置 
改变扫描路径:
①:@SpringBootApplication(scanBasePackages="com.lun")

②:@ComponentScan 指定扫描路径----》因为
@SpringBootApplication 等同于 
@SpringBootConfiguration 
@EnableAutoConfiguration
@ComponentScan("com.lun")

2、各种配置拥有默认值

配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
例如:
spring.rabbitmq.host=122.51.109.18
spring.rabbitmq.username=admin
spring.rabbitmq.password=hx801219
spring.rabbitmq.port=5672

在这里插入图片描述

3、按需加载所有自动配置项

非常多的starter 
引入了哪些场景这个场景的自动配置才会开启

SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
例如:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
进入里面,得到
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>3.1.6</version>
    <scope>compile</scope>
</dependency>
再进入里面,得到
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>3.1.6</version>
    <scope>compile</scope>
</dependency>
对应到目录里面如下:

在这里插入图片描述

4.springboot自动配置原理详解

我们都知道SpringBoot启动的时候先加载主程序类(主程序类也叫主配置类),主程序类被@SpringBootApplication标注,查看此注解源码我们发现,此注解是由:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.laizhenghua.boot_helloworld")
这三个注解合成,如下所示:


// @SpringBootApplication // 标注SpringBoot应用
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.laizhenghua.boot_helloworld")
public class MainApplication {
    public static void main(String[] args) {
        
        SpringApplication.run(MainApplication.class, args);
    }
}

4.1、@SpringBootConfiguration

点进去@SpringBootConfiguration,发现被@Configuration标注,这也说明:主程序类也是一个配置类。

4.2、@ComponentScan

前面已经介绍过了,是一个Spring的注解,用来指定包的扫描范围!

加了包扫描@ComponentScan注解后,只要标注了@Controller、@Service、@Repository、@Component注解中的任何一个,其组件都会被自动扫描,加入到容器中。

例如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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启注解支持-->
    <context:annotation-config/>
    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.howie"/>
</beans>

4.3、@EnableAutoConfiguration – 核心注解

SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration。此注解也是SpringBoot自动配置的核心注解,并且也是一个合成注解!

// 由以下两个注解合成
...
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	...
}
4.3.1、@AutoConfigurationPackage
自动配置包?指定了默认的包规则!
点进去此注解:
...
@Import(AutoConfigurationPackages.Registrar.class) // 给容器中导入一个组件
public @interface AutoConfigurationPackage {
	...
}

然后我们可以看到其中的一段代码:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }
        
        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { 
        	// 进行批量注册
            AutoConfigurationPackages.register(registry, (String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }
        
        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new PackageImports(metadata));
        }
        
	}

在这里插入图片描述

在这里插入图片描述

我们可以看到:
利用Registrar给容器中导入一系列组件
将指定的一个包下的所有组件导入进来?MainApplication 所在包下。

这里就是获取了主配置类的信息,利用Registrar给容器中导入了主配置类子包中声明的所有组件!
4.3.2、@Import(AutoConfigurationImportSelector.class)
给容器中导入了类型为AutoConfigurationImportSelector的组件,然后我们查看此类到底做了些什么?

1.利用getAutoConfigurationEntry(annotationMetadata)方法,给容器中批量导入一些组件。
2.调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes),获取到所有需要导入到容器中的配置类。

在这里插入图片描述

3.利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader),得到所有的组件,我们点进去可以看到:

在这里插入图片描述

4.从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.9.RELEASE.jar包里面也有META-INF/spring.factories,如下:

在这里插入图片描述

小结:

1.通过注解@AutoConfigurationPackage里面合成的注解,加载主配置类下子包中声明的所有组件。例如:使用@Controller、@Service、@Bean、@Mapper、@Configuration等注解标注的类或方法,将类或方法(变成了组件)注册到容器中。
2.通过注解@Import(AutoConfigurationImportSelector.class)将所有META-INF/spring.factories位置的文件中写死的全类名组件(配置类)都注入容器中。
3.需要注意的是不一定每一个配置类里或类里面的声明的组件都有用,如果全部都加载了,对内存对资源是一种极大的浪费,所以在SpringBoot里有了按需开启自动配置项 !
4.3.3、按需开启自动配置项
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。

4.4、自动配置流程

1.SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
2.每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里xxxProperties和全局配置文件进行了绑定
3.生效的配置类就会给容器中装配很多组件
4.只要容器中有这些组件,相当于这些功能就有了
5.只要用户有自己配置的,就以用户的优先

定制化配置:
1.开发者直接自己@Bean替换底层的组件
2.开发者去看这个组件是获取的配置文件什么值就去修改

器中。
2.通过注解@Import(AutoConfigurationImportSelector.class)将所有META-INF/spring.factories位置的文件中写死的全类名组件(配置类)都注入容器中。
3.需要注意的是不一定每一个配置类里或类里面的声明的组件都有用,如果全部都加载了,对内存对资源是一种极大的浪费,所以在SpringBoot里有了按需开启自动配置项 !


#### 4.3.3、按需开启自动配置项

```tex
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。

4.4、自动配置流程

1.SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
2.每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里xxxProperties和全局配置文件进行了绑定
3.生效的配置类就会给容器中装配很多组件
4.只要容器中有这些组件,相当于这些功能就有了
5.只要用户有自己配置的,就以用户的优先

定制化配置:
1.开发者直接自己@Bean替换底层的组件
2.开发者去看这个组件是获取的配置文件什么值就去修改
  • 29
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值