springboot ioc通过扫描装配bean

本文介绍了SpringBoot项目中如何通过AppConfig.java配置类进行IOC容器的bean扫描和装配,涉及到User.java组件的使用,并在TestApplication.java测试类中进行了验证和应用。

项目架构为

AppConfig.java:

package com.nice.boot.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author ningh
 */
@Configuration
@ComponentScan
public class AppConfig {
}

 

User.java:

package com.nice.boot.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author ningh
 */
@Component("user")
@Data
public class User {


    @Value("1")
    private Long id;

    @Value("nice")
    private String userName;

    @Value("感觉不会再爱了")
    private String note;


}

TestApplication.java

package com.nice.boot;

import com.nice.boot.config.AppConfig;
import com.nice.boot.config.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author ningh
 */
public class TestApplication {

    @Test
    public void test(){
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = context.getBean(User.class);
        System.out.println(user);
    }

}
<?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.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.nice.boot</groupId>
    <artifactId>boot-chapter3</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>boot-chapter3</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

运行测试类:

D:\Java\jdk1.8.0_202\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.scala\lib\idea_rt.jar=59465:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.scala\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.scala\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.scala\plugins\junit\lib\junit-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.scala\plugins\junit\lib\junit5-rt.jar;D:\Java\jdk1.8.0_202\jre\lib\charsets.jar;D:\Java\jdk1.8.0_202\jre\lib\deploy.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\cldrdata.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\dnsns.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\jaccess.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\jfxrt.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\localedata.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\nashorn.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\sunec.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\sunmscapi.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk1.8.0_202\jre\lib\ext\zipfs.jar;D:\Java\jdk1.8.0_202\jre\lib\javaws.jar;D:\Java\jdk1.8.0_202\jre\lib\jce.jar;D:\Java\jdk1.8.0_202\jre\lib\jfr.jar;D:\Java\jdk1.8.0_202\jre\lib\jfxswt.jar;D:\Java\jdk1.8.0_202\jre\lib\jsse.jar;D:\Java\jdk1.8.0_202\jre\lib\management-agent.jar;D:\Java\jdk1.8.0_202\jre\lib\plugin.jar;D:\Java\jdk1.8.0_202\jre\lib\resources.jar;D:\Java\jdk1.8.0_202\jre\lib\rt.jar;D:\ideapro\boot-chapter3\target\test-classes;D:\ideapro\boot-chapter3\target\classes;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot-starter\2.2.0.RELEASE\spring-boot-starter-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot\2.2.0.RELEASE\spring-boot-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\spring-context\5.2.0.RELEASE\spring-context-5.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\spring-aop\5.2.0.RELEASE\spring-aop-5.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\spring-beans\5.2.0.RELEASE\spring-beans-5.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\spring-expression\5.2.0.RELEASE\spring-expression-5.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.2.0.RELEASE\spring-boot-autoconfigure-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.2.0.RELEASE\spring-boot-starter-logging-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\ningh\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\ningh\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.12.1\log4j-to-slf4j-2.12.1.jar;C:\Users\ningh\.m2\repository\org\apache\logging\log4j\log4j-api\2.12.1\log4j-api-2.12.1.jar;C:\Users\ningh\.m2\repository\org\slf4j\jul-to-slf4j\1.7.28\jul-to-slf4j-1.7.28.jar;C:\Users\ningh\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\ningh\.m2\repository\org\springframework\spring-core\5.2.0.RELEASE\spring-core-5.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\spring-jcl\5.2.0.RELEASE\spring-jcl-5.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\yaml\snakeyaml\1.25\snakeyaml-1.25.jar;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot-devtools\2.2.0.RELEASE\spring-boot-devtools-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\projectlombok\lombok\1.18.10\lombok-1.18.10.jar;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.2.0.RELEASE\spring-boot-starter-test-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot-test\2.2.0.RELEASE\spring-boot-test-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.2.0.RELEASE\spring-boot-test-autoconfigure-2.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;C:\Users\ningh\.m2\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar;C:\Users\ningh\.m2\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;C:\Users\ningh\.m2\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;C:\Users\ningh\.m2\repository\org\slf4j\slf4j-api\1.7.28\slf4j-api-1.7.28.jar;C:\Users\ningh\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.2\jakarta.xml.bind-api-2.3.2.jar;C:\Users\ningh\.m2\repository\jakarta\activation\jakarta.activation-api\1.2.1\jakarta.activation-api-1.2.1.jar;C:\Users\ningh\.m2\repository\org\junit\jupiter\junit-jupiter\5.5.2\junit-jupiter-5.5.2.jar;C:\Users\ningh\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.5.2\junit-jupiter-api-5.5.2.jar;C:\Users\ningh\.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;C:\Users\ningh\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\ningh\.m2\repository\org\junit\platform\junit-platform-commons\1.5.2\junit-platform-commons-1.5.2.jar;C:\Users\ningh\.m2\repository\org\junit\jupiter\junit-jupiter-params\5.5.2\junit-jupiter-params-5.5.2.jar;C:\Users\ningh\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.5.2\junit-jupiter-engine-5.5.2.jar;C:\Users\ningh\.m2\repository\org\junit\platform\junit-platform-engine\1.5.2\junit-platform-engine-1.5.2.jar;C:\Users\ningh\.m2\repository\org\mockito\mockito-junit-jupiter\3.1.0\mockito-junit-jupiter-3.1.0.jar;C:\Users\ningh\.m2\repository\org\assertj\assertj-core\3.13.2\assertj-core-3.13.2.jar;C:\Users\ningh\.m2\repository\org\hamcrest\hamcrest\2.1\hamcrest-2.1.jar;C:\Users\ningh\.m2\repository\org\mockito\mockito-core\3.1.0\mockito-core-3.1.0.jar;C:\Users\ningh\.m2\repository\net\bytebuddy\byte-buddy\1.10.1\byte-buddy-1.10.1.jar;C:\Users\ningh\.m2\repository\net\bytebuddy\byte-buddy-agent\1.10.1\byte-buddy-agent-1.10.1.jar;C:\Users\ningh\.m2\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\Users\ningh\.m2\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\Users\ningh\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\ningh\.m2\repository\org\springframework\spring-test\5.2.0.RELEASE\spring-test-5.2.0.RELEASE.jar;C:\Users\ningh\.m2\repository\org\xmlunit\xmlunit-core\2.6.3\xmlunit-core-2.6.3.jar;C:\Users\ningh\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\ningh\.m2\repository\org\hamcrest\hamcrest-core\2.1\hamcrest-core-2.1.jar" com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 com.nice.boot.TestApplication,test

02:07:06.982 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@57829d67
02:07:07.194 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
02:07:07.239 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\ideapro\boot-chapter3\target\classes\com\nice\boot\config\User.class]
02:07:07.298 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
02:07:07.300 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
02:07:07.301 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
02:07:07.302 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
02:07:07.308 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
02:07:07.312 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
User(id=1, userName=nice, note=感觉不会再爱了)



Process finished with exit code 0

 

<think>我们正在讨论Spring Boot中的IoC概念及其工作原理。根据引用内容,IoC(控制反转)是Spring框架的核心思想,其本质是将对象的创建、管理、依赖关系的维护交给Spring容器来完成,而不是由开发者手动管理。在Spring Boot中,IoC的实现原理与Spring框架一致,但Spring Boot通过自动配置等机制简化了配置过程。 ### IoC的概念 IoC(Inversion of Control,控制反转)是一种设计原则,用于降低代码之间的耦合度。传统方式中,对象之间的依赖关系由程序代码直接控制(例如通过`new`关键字创建对象),这会导致较高的耦合度。而IoC方式将对象的创建和依赖关系的管理交给一个容器(即IoC容器)来处理,程序只需声明需要哪些对象,容器负责在运行时创建并注入这些对象。 ### Spring IoC容器 Spring IoC容器是Spring框架的核心,负责管理对象的生命周期和依赖关系。容器通过读取配置信息(XML文件、Java注解或Java代码)来创建对象,并处理对象之间的依赖注入(DI)。 ### 依赖注入(DI) 依赖注入(Dependency Injection,DI)是实现IoC的一种方式。Spring通过DI机制,将对象所依赖的其他对象自动注入到目标对象中,而不需要目标对象主动去获取。依赖注入的方式主要有三种: 1. **构造器注入**:通过构造方法注入依赖对象。 2. **Setter注入**:通过Setter方法注入依赖对象。 3. **字段注入**:通过反射直接注入字段(例如使用`@Autowired`注解)。 ### Spring Boot中的IoC Spring Boot基于Spring框架,因此其IoC原理与Spring一致。但Spring Boot通过以下机制简化了配置: 1. **自动配置(Auto-configuration)**:Spring Boot根据项目依赖自动配置Spring容器。例如,当项目中包含`spring-boot-starter-web`依赖时,Spring Boot会自动配置Tomcat和Spring MVC。 2. **组件扫描(Component Scanning)**:Spring Boot会自动扫描主配置类(带有`@SpringBootApplication`注解的类)所在包及其子包中的组件(如`@Component`、`@Service`、`@Repository`等注解标记的类),并将这些组件注册到IoC容器中。 3. **条件化配置(Conditional Configuration)**:Spring Boot使用`@Conditional`系列注解,根据特定条件决定是否创建某个Bean。 ### IoC容器的工作原理 Spring IoC容器的工作流程可以分为以下几个步骤: 1. **加载配置**:容器根据配置源(XML、Java注解或Java配置类)加载Bean的定义信息(BeanDefinition)。 2. **实例化Bean**:容器根据Bean的定义信息,使用反射机制创建Bean的实例。 3. **依赖注入**:容器解析Bean之间的依赖关系,并将依赖对象注入到目标Bean中(例如通过构造器、Setter方法或字段注入)。 4. **初始化Bean**:如果Bean实现了特定的生命周期接口(如`InitializingBean`),容器会调用其初始化方法(如`afterPropertiesSet()`)。 5. **使用Bean**:应用程序可以通过容器获取并使用Bean。 6. **销毁Bean**:当容器关闭时,会调用Bean的销毁方法(如果Bean实现了`DisposableBean`接口)。 ### 示例:使用注解定义和注入Bean 在Spring Boot中,通常使用注解来声明Bean和依赖关系。例如: ```java @Service public class UserService { // 业务逻辑 } @RestController public class UserController { @Autowired // 自动注入UserService实例 private UserService userService; } ``` 在上面的代码中: - `@Service`注解告诉Spring容器,`UserService`类是一个需要被管理的Bean。 - `@RestController`注解标记`UserController`为控制器,并同时将其注册为Bean。 - `@Autowired`注解指示容器自动将`UserService`的实例注入到`userService`字段中。 ### 总结 Spring Boot的IoC机制基于Spring框架,通过控制反转和依赖注入实现了对象之间的解耦。Spring Boot进一步简化了配置,使得开发者可以更专注于业务逻辑。IoC容器负责管理Bean的整个生命周期,包括创建、依赖注入、初始化和销毁。 §§相关问题§§ 1. Spring Boot中如何自定义Bean的初始化方法? 2. 什么是循环依赖?Spring如何解决循环依赖问题? 3. Spring Boot中的自动配置是如何工作的? 4. 如何通过Java配置类(@Configuration)定义Bean?</think>### Spring Boot IOC 概念与工作原理 #### 1. **IOC 核心概念** IOC(Inversion of Control,控制反转)是 Spring 框架的核心思想,在 Spring Boot 中通过自动配置进一步简化。其核心是**将对象的创建、依赖管理和生命周期交给容器控制**,而非开发者手动处理(如 `new` 对象)[^1][^2]。 #### 2. **IOC 工作原理** ##### (1) **容器初始化** - **启动入口**:Spring Boot 通过 `@SpringBootApplication` 注解触发容器初始化。 - **组件扫描**:容器自动扫描 `@Component`、`@Service`、`@Repository` 等注解的类,将其注册为 Bean 定义(BeanDefinition)[^1]。 - **配置加载**:读取 `application.properties` 或 Java 配置类(`@Configuration`),定义 Bean 的依赖规则。 ##### (2) **依赖注入(DI)** 依赖注入是 IOC 的实现方式,容器在运行时自动装配对象间的依赖关系[^1][^2]: ```java @Service public class UserService { // 容器自动注入 UserRepository 实例 @Autowired private UserRepository userRepo; } ``` - **注入方式**: - `@Autowired`:按类型自动装配(默认)。 - `@Qualifier`:按名称装配(解决同一类型多个 Bean 的问题)[^3]。 - 构造器注入(推荐):避免循环依赖。 ##### (3) **Bean 生命周期管理** 容器负责 Bean 的完整生命周期: 1. **实例化**:通过反射创建对象。 2. **属性填充**:注入依赖的 Bean。 3. **初始化**:调用 `@PostConstruct` 方法或实现 `InitializingBean`。 4. **销毁**:调用 `@PreDestroy` 方法或实现 `DisposableBean`。 #### 3. **Spring Boot 的增强机制** - **自动配置(Auto-Configuration)**: 基于类路径依赖(如 `spring-boot-starter-web`),自动配置 Tomcat、Spring MVC 等组件。 - **条件化装配**: 使用 `@ConditionalOnClass` 等注解,仅在满足条件时创建 Bean(如:当存在 `DataSource` 类时才装配数据库连接池)。 #### 4. **IOC 的优势** 1. **解耦**:对象无需关注依赖的创建细节。 2. **可测试性**:依赖可替换为 Mock 对象。 3. **统一管理**:单例 Bean 减少资源消耗,通过容器配置统一修改行为。 ### 示例:IOC 工作流程 假设有 `UserService` 依赖 `UserRepository`: ```java @Repository public class UserRepository { /* 数据库操作 */ } @Service public class UserService { @Autowired private UserRepository repository; // 容器自动注入 } ``` **容器执行步骤**: 1. 扫描到 `UserRepository` 和 `UserService` 的注解。 2. 创建 `UserRepository` 实例。 3. 创建 `UserService` 实例,并将 `UserRepository` 注入其属性。 4. 返回完全装配的 `UserService` Bean 供其他组件使用。 > 总结:Spring Boot IOC 通过容器接管对象的创建与依赖装配,结合自动配置机制,显著简化了开发复杂度,使开发者聚焦业务逻辑而非基础设施[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值