IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot 自动装配的原理简析 -> 正文阅读

[Java知识库]SpringBoot 自动装配的原理简析

首先通过一个案例来看一下自动装配的效果,创建一个?SpringBoot?的项目,在?pom?文件中加入下面的依赖。

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

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

其中?web?的依赖表示我们这是一个?web?项目,redis?的依赖就是我们这边是要验证的功能依赖。随后在?application.properties?配置文件中增加?redis?的相关配置如下

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=123456

?再编写一个?Controller?和?Service?类,相关代码如下。

package com.example.demo.controller;

import com.example.demo.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

  @Autowired
  private HelloService helloService;
  
  @GetMapping(value = "/hello")
  public String hello(@RequestParam("name") String name) {
    return helloService.sayHello(name);
  }

}







package com.example.demo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class HelloService {

  @Autowired
  RedisTemplate<String, String> redisTemplate;

  public String sayHello(String name) {
    String result = doSomething(name);
    redisTemplate.opsForValue().set("name", result);
    result = redisTemplate.opsForValue().get("name");
    return "hello: " + result;
  }

  private String doSomething(String name) {
    return name + " 欢迎";
  }

}

?启动项目,然后我们通过访问 http://127.0.0.1:8080/hello?name=XXX,可以看到正常访问。接下来我们再通过?Redis?的客户端,去观察一下数据是否正确的写入到?Redis?中,效果跟我们想象的一致。

虽然用起来是很爽,但是大家有没有想过一个问题,那就是在我们的?HelloService?中通过?@Autowired?注入了一个?RedisTemplate?类,但是我们的代码中并没有写过这个类,也没有使用类似于@RestController,@Service?这样的注解将?RedisTemplate?注入到?Spring IoC?容器中,那为什么我们就可以通过?@Autowired??注解从?IoC?容器中获取到?RedisTemplate??这个类呢?这里就是常说的自动装配的功能了。?

首先我们看下项目的启动类,

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(value = "com.example.demo.*")
public class DemoApplication {

 public static void main(String[] args) {
  SpringApplication.run(DemoApplication.class, args);
 }
}

?在启动类上面有一个?@SpringBootApplication?注解,我们点进去可以看到如下内容

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
   // 省略
}

?在这个注解中,其中有一个?@EnableAutoConfiguration?注解,正是因为有了这样一个注解,我们才得以实现自动装配的功能。继续往下面看。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

可以看到?@EnableAutoConfiguration?注解中有一个?@Import({AutoConfigurationImportSelector.class}),导入了一个 ?AutoConfigurationImportSelector?类,该类间接实现了?ImportSelector?接口,实现了一个?String[] selectImports(AnnotationMetadata importingClassMetadata);?方法,这个方法的返回值是一个字符串数组,对应的是一系列主要注入到?Spring IoC?容器中的类名。当在?@Import?中导入一个?ImportSelector?的实现类之后,会把该实现类中返回的?Class?名称都装载到?IoC?容器中。

一旦被装载到?IoC?容器中过后,我们在后续就可以通过?@Autowired??来进行使用了。接下来我们看下?selectImports?方法里面的实现,当中引用了?getCandidateConfigurations?方法 ,最终会加载 “META-INF/spring.factories” 文件里配置的一些

	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

?

?

?我们可以看到这个文件中有一个?RedisAutoConfiguration?配置类,在这个配置中就有我们需要的?RedisTemplate?类的?Bean,同时也可以看到,在类上面有一个?@ConditionalOnClass({RedisOperations.class})?注解,表示只要在类路径上有?RedisOperations.class?这个类的时候才会进行实例化。这也就是为什么只要我们添加了依赖,就可以自动装配的原因。

通过? “META-INF/spring.factories”??这个文件,我们可以看到有很多官方帮我们实现好了配置类,这些功能只要我们在?pom?文件中添加对应的?starter?依赖,然后做一些简单的配置就可以直接使用。

其中本质上自动装配的原理很简单,本质上都需要实现一个配置类,只不过这个配置类是官方帮我们创建好了,再加了一些条件类注解,让对应的实例化只发生类类路径存在某些类的时候才会触发。这个配置类跟我们平常自己通过?JavaConfig?形式编写的配置类没有本质的区别。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 18:50:24  更:2022-08-19 18:51:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:17:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码