SpringBoot自动注入bean原理

自动注入原理

参考Spring Cloud Alibaba 微服务原理与实战 3.3

@SpringBootApplication

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

在这里插入图片描述

AutoConfigurationImportSelector.class

@SpringBootApplication的
@EnableAutoConfiguration中@Import(AutoConfigurationImportSelector.class)

改类实现了ImportSelector接口

public interface ImportSelector {
	//这个方法返回的都会被注入容器中
    String[] selectImports(AnnotationMetadata importingClassMetadata);

    @Nullable
    default Predicate<String> getExclusionFilter() {
        return null;
    }
}

AutoConfigurationImportSelector#selectImports

public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		//从
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
  • getAutoConfigurationEntry 主要根据这个方法找到需要注入的bean
  • getConfigurations() 单纯get数组返回

AutoConfigurationImportSelector#getAutoConfigurationEntry

作用:获取到要配置的类,根据一些规则排除掉一些类

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		//获取@EnableAutoConfiguration中的属性
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		//获得所有自动装配的配置类,后面分析
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		//去除重复配置项目
		configurations = removeDuplicates(configurations);
		//根据@EnableAutoConfiguration中的属性去除一些配置类
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = getConfigurationClassFilter().filter(configurations);
		//广播事件
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

AutoConfigurationImportSelector#getCandidateConfigurations
作用:这个方法是真正从文件中获取配置类的方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		//这个load就是从配置文件中读取一堆Configurations的配置类
		List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
				.getCandidates();
		Assert.notEmpty(configurations,
				"No auto configuration classes found in "
						+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

这个方法老版本的boot和新版本的boot有所不用(此处是新版本)

  • 老版本
    在这里插入图片描述
    会先从.propertiest的这个文件中得到自动装配条件然后再从spring.factories中获得对应的configuration配置类

  • 新版本
    在这里插入图片描述
    直接读取这个文件,里面就是一批的configuration配置类

在这些configuration类中根据条件再来判断是否加载,就可以实现按需加载
例如
在这里插入图片描述

@Conditional 按需加载

这个注解是spring中的,可以实现Condition接口来实现是否注入,springboot进行了优化
在这里插入图片描述
可以作用于类或者方法上

自己实现@Enable…类似注解

自己也能实现类似的@Enable…注解

//想要注入的类
public class User {}
public class Person {}

实现了ImportSelector 接口

public class myConfig implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{Person.class.getName(),User.class.getName()};
    }
}

自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(myConfig.class)
public @interface EnableMyBean {
}

在启动类上加上注解即可注入自己的bean

@SpringBootApplication
@EnableMyBean
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

自定义starter

Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境( 条件)进行自动配置。使用者只需要依赖相应功能的Starter,无需做过多的配置和依赖,Spring Boot就能自动扫描并加载相应的模块。
总结:

  • 它整合了这个模块需要的依赖库;
  • 提供对模块的配置项给使用者、并可以对配置项提供默认值,使得使用者可以不指定配置时提供默认配置项值,也可以根据需要指定配置项值;
  • 提供自动配置类对模块内的Bean进行自动装配

例如,在Maven的依赖中加入spring-boot-starter-web就能使项目支持Spring MVC,并且Spring Boot还为我们做了很多默认配置,无需再依赖spring-web、spring-webmvc等相关包及做相关配置就能够立即使用起来。

例如:一个模块只有一个User类,但是通过这个starter可以根据配置文件来配置默认的User类属性,并自动加入容器

首先创建一个新项目,并使用maven install 加入到仓库
在这里插入图片描述
如果没有自动注入使用的时候new出对象,现在改写成starter实现自动注入并且初始化值

1.新建一个spingboot项目(3.0要支持jdk17,所以创建2.7.8的版本),修改配置文件,否则其他项目无法读取依赖
在这里插入图片描述
2.编写配置类

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "chen.user")
@Data
public class myUserProperties {
    private String name = "ck";
    private Integer age = 66;
}

@ConfigurationProperties(prefix = “chen.user”) 代表是配置文件的前缀为chen.user。
等于默认配置chen.user.name = ck 和 chen.user.age = 66,要配合@EnableConfigurationProperties或者@Configuration才有效果,如果配置文件中相同的属性则替换

@Configuration
//引入配置类
@EnableConfigurationProperties(myUserProperties.class)
//加载条件
@ConditionalOnClass(MyUser.class)
public class myUserConfig {


    @Bean
    //配置文件中chen.user.enalbe = true才会注入这个bean
    @ConditionalOnProperty(value = "chen.user.enable",havingValue = "true")
    public MyUser myUser(myUserProperties myUserProperties)
    {
        MyUser myUser = new MyUser();
        myUser.setName(myUserProperties.getName());
        myUser.setAge(myUserProperties.getAge());
        return myUser;
    }
}

3.编写配置文件(根据自动注入原理)
在这里插入图片描述
spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.chenke.myusertestspringbootstarter.config.myUserConfig

org.springframework.boot.autoconfigure.AutoConfiguration.imports

com.chenke.myusertestspringbootstarter.config.myUserConfig

测试下这两个文件只要有其中一个就可以写入

4.install这个springboot项目

5.在其他的springboot引入这个依赖

   <dependency>
            <groupId>com.chenke</groupId>
            <artifactId>myusertest-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
    </dependency>

application.properties

//根据自己设定 为true才会注入
chen.user.enable = true

//如果不写这两个将用默认值
chen.user.name = zssm
chen.user.age = 250

项目启动后容器中就会自动存在一个 MyUser(name=zssm, age=250)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: SpringBoot注入Bean的原理是基于Spring框架的依赖注入(DI)机制实现的。在SpringBoot中,我们可以使用注解来标记需要注入Bean,例如@Service、@Component、@Repository等。当SpringBoot启动时,它会扫描所有被标记的类,并将它们实例化为Bean对象。这些Bean对象可以被其他类所引用,从而实现了依赖注入的功能。 SpringBoot注入Bean的原理还涉及到Spring框架的IoC容器。IoC容器是Spring框架的核心,它负责管理Bean的生命周期、依赖关系和作用域等。在SpringBoot中,IoC容器会自动创建并管理所有被注入Bean对象,同时也会自动解决Bean之间的依赖关系。 总之,SpringBoot注入Bean的原理是基于Spring框架的依赖注入机制和IoC容器实现的。通过使用注解标记需要注入Bean,SpringBoot可以自动创建和管理这些Bean对象,并解决它们之间的依赖关系,从而实现了高效的应用程序开发。 ### 回答2: SpringBoot是一款基于Spring框架的快速开发框架,它的IOC容器可以自动扫描注解并注入bean对象。SpringBoot自动注入bean的原理主要是基于Spring的依赖注入(DI)和反射机制实现的。 在SpringBoot中,我们可以通过注解的方式让Spring自动扫描并实例化对象,这些注解包括@Component、@Service、@Repository、@Controller等。当SpringBoot启动时,它会自动扫描被这些注解标记的类,实例化对象,并将它们注册到IOC容器中。这些被注册到IOC容器中的对象称为bean,它们可以被其他对象引用和调用。 当我们需要注入一个bean时,SpringBoot会根据其类型和名称在IOC容器中查找对应的对象,并将它注入到需要它的对象中。这个过程主要依赖于Spring的依赖注入和反射机制。 依赖注入指的是通过构造器、Set方法或者成员变量的方式将对象注入到另一个对象中。在SpringBoot中,我们主要使用@Autowired注解进行注入。当SpringBoot发现一个类中使用了@Autowired注解时,它会自动扫描IOC容器中与这个类匹配的对象,并将其注入到变量中。 反射机制则是Java中的一种特殊机制,它可以在程序运行时获取和操作对象的信息。在SpringBoot注入bean过程中,反射机制主要用于动态创建对象并设置其属性。SpringBoot会通过反射机制调用构造器和Set方法,并将需要注入的对象传递进去。 综上所述,SpringBoot注入bean的原理主要依赖于Spring的依赖注入和反射机制。SpringBoot自动扫描被注解标识的类,将其实例化成bean,并注册到IOC容器中。当需要注入一个对象时,SpringBoot会在IOC容器中查找对应的对象,并使用依赖注入和反射机制将其注入到需要它的对象中。 ### 回答3: SpringBoot是一个优秀的快速开发框架,其注入Bean的原理可以分为以下几步: 1. 将JavaBean类加上@Component注释,表示该类是一个组件。 2. 在SpringApplication类中创建一个Spring容器。 3. Spring容器在启动时扫描所有被@Component注解的组件,并将其创建出来。 4. Spring容器将所有组件存储到一个BeanDefinitionMap中,这个Map中存储了所有需要注入的组件及其对应的注入方式和参数。 5. 当需要使用某个组件时,Spring容器会根据组件的类型和名称,找到该组件的BeanDefinition,进而生成该组件的实例并注入到需要使用它的地方。 通过上述的步骤,SpringBoot实现了Bean依赖注入的功能。在其注入Bean的过程中,主要使用了反射技术、BeanDefinitionMap以及自动扫描等技术。Bean依赖注入的实现,使得SpringBoot框架可以更加灵活地完成组件的管理和调用,大大提高了其开发效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值