Spring IOC:容器管理与依赖注入秘籍

Java Spring 核心容器、IOC


一、IOC(控制反转)核心概念

基本概念

控制反转 是一种将对象的创建、依赖关系的管理和生命周期的控制权从应用程序代码转移到外部容器的设计原则 。在传统编程中,对象的创建和依赖关系是由程序自身控制的,而在 IOC 模式下,控制权被反转给了一个专门的容器。这个容器负责创建对象、注入依赖,并管理对象的生命周期,使得代码更加松散耦合,提高了可维护性和可测试性。

为什么需要 IOC

降低耦合度

在传统的编程方式中,一个类往往需要自己负责创建和管理它所依赖的对象。这会导致类与类之间的耦合度很高当依赖的对象发生变化时,需要修改多个地方的代码而使用 IOC 可以将对象的创建和依赖关系的管理交给容器,使得类只需要关注自身的业务逻辑,降低了类与类之间的耦合度。

提高可测试性

在使用 IOC 的情况下,可以很方便地为类注入模拟对象,从而进行单元测试。因为对象的依赖是通过外部注入的,所以可以在测试时轻松替换依赖对象,使得测试更加简单和可靠。

便于代码维护和扩展

由于对象的创建和依赖关系的管理都集中在容器中,当需要修改或扩展功能时,只需要修改容器的配置,而不需要修改大量的业务代码。这使得代码的维护和扩展变得更加容易。

  • 传统方式 :对象主动创建依赖(new 操作)。

  • IOC 方式 :容器负责创建对象并注入依赖,实现解耦。


二、容器(Container)

Spring 容器是 Spring 框架的核心部分,它负责创建、管理和装配 Bean 对象,以及处理 Bean 之间的依赖关系。以下是关于 Spring 容器的详细介绍:

概念

Spring 容器是一个轻量级的反转控制(IoC)容器,也被称为依赖注入(DI)容器。它通过读取配置文件扫描注解来创建和管理对象,并将对象之间的依赖关系进行注入,从而实现了对象之间的解耦。

工作原理

  • Bean 的定义和注册 :在 Spring 中,Bean 是被容器管理的对象。开发者通过配置文件(如 XML)或注解(如@Component @Service等)来定义 Bean,并将其注册到 Spring 容器中。容器会解析这些配置信息,创建相应的 BeanDefinition 对象,用于描述 Bean 的各种属性,如类名、构造函数参数、属性值等。
  • Bean 的创建和初始化:当 Spring 容器启动时,它会根据 BeanDefinition 创建 Bean 实例。对于单例模式的 Bean,容器在启动时就会创建并初始化它们;对于原型模式的 Bean,在每次请求获取 Bean 时才会创建。在创建 Bean 的过程中,容器会调用 Bean 的构造函数进行实例化,然后根据配置信息设置 Bean 的属性值,并调用 Bean 的初始化方法(如果有指定)。
  • 依赖注入Spring 容器通过依赖注入来解决 Bean 之间的依赖关系。当一个 Bean 依赖于其他 Bean 时,容器会在创建该 Bean 时,自动将其依赖的 Bean 注入到该 Bean 中。依赖注入的方式有三种:构造函数注入、Setter 方法注入和字段注入。

主要类型

  • BeanFactory:是 Spring 容器的最基本接口,提供了基本的 Bean 管理功能,如获取 Bean 实例、检查 Bean 的存在等。它是一个延迟加载的容器,只有在真正需要使用 Bean 时才会创建和初始化。
  • ApplicationContext:是 BeanFactory 的子接口,它在 BeanFactory 的基础上增加了许多企业级应用所需的功能,如国际化支持、资源加载、事件发布等。ApplicationContext 在启动时会预先实例化所有的单例 Bean,适用于大多数 Spring 应用场景。

作用

  • 解耦对象之间的依赖关系:通过 Spring 容器的依赖注入功能,对象之间的依赖关系由容器来管理,使得对象之间的耦合度大大降低。这样,当一个对象的依赖发生变化时,只需要在容器的配置中进行修改,而不需要在使用该对象的代码中进行大量的修改。
  • 提高代码的可维护性和可扩展性:Spring 容器将对象的创建和管理集中到一个地方,使得代码的结构更加清晰,易于维护。同时,当需要增加新的功能或修改现有功能时,可以通过在容器中注册新的 Bean 或修改现有 Bean 的配置来实现,而不需要对大量的业务代码进行修改,提高了代码的可扩展性。
  • 方便进行面向切面编程(AOP):Spring 容器与 AOP 框架紧密集成,可以方便地实现对 Bean 的切面编程。通过 AOP,可以在不修改业务逻辑代码的情况下,对 Bean 的方法进行增强,如添加日志记录、事务管理、权限控制等功能。

创建 Spring 容器

在 Spring 中,常见的创建容器的方式有基于ApplicationContextBeanFactory两种,这里以ApplicationContext为例,它有多个实现类,下面分别介绍基于 XML 配置和注解配置创建容器的方法。

基于 XML 配置创建容器
java 复制代码
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class XmlBasedContainerExample {
    public static void main(String[] args) {
        // 通过加载类路径下的XML配置文件创建ApplicationContext容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 从容器中获取Bean
        Object myBean = context.getBean("myBean");
        System.out.println(myBean);
    }
}
基于注解配置创建容器
java 复制代码
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.example.demo")
class AppConfig {
    // 配置类
}

public class AnnotationBasedContainerExample {
    public static void main(String[] args) {
        // 通过注解配置类创建ApplicationContext容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 从容器中获取Bean
        Object myBean = context.getBean("myBean");
        System.out.println(myBean);
    }
}

Spring 容器类的层次结构

Spring 容器的核心接口是BeanFactoryApplicationContext,它们的类层次结构大致如下:

  • BeanFactory :是 Spring 容器的最基础接口,提供了获取 Bean 的基本方法,如getBean等。它是一个延迟加载的容器,只有在真正需要使用 Bean 时才会创建和初始化。
  • HierarchicalBeanFactory :继承自BeanFactory,增加了对父子容器层次结构的支持,可以获取父容器。
  • ListableBeanFactory :继承自BeanFactory,提供了可以枚举容器中所有 Bean 的功能,如获取所有 Bean 的名称、根据类型获取所有 Bean 等。
  • ApplicationContext :继承自HierarchicalBeanFactoryListableBeanFactory,并扩展了许多企业级应用所需的功能,如国际化支持、资源加载、事件发布等。它在启动时会预先实例化所有的单例 Bean。
    • ClassPathXmlApplicationContext:从类路径下的 XML 配置文件中加载 Bean 定义。
    • FileSystemXmlApplicationContext:从文件系统中的 XML 配置文件中加载 Bean 定义。
    • AnnotationConfigApplicationContext:基于 Java 注解配置类来加载 Bean 定义。

BeanFactory

BeanFactory是 Spring 容器的核心接口,它是一个轻量级的容器,主要负责创建、管理和查找 Bean。以下是一个简单的BeanFactory使用示例:

java 复制代码
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

// 注意:XmlBeanFactory在Spring 3.1中已被弃用,这里仅作示例
@SuppressWarnings("deprecation")
public class BeanFactoryExample {
    public static void main(String[] args) {
        // 加载XML配置文件
        Resource resource = new ClassPathResource("applicationContext.xml");
        // 创建BeanFactory容器
        BeanFactory factory = new XmlBeanFactory(resource);
        // 从容器中获取Bean
        Object myBean = factory.getBean("myBean");
        System.out.println(myBean);
    }
}

在实际开发中,由于BeanFactory功能相对基础,大多数情况下会使用功能更强大的ApplicationContext。不过,了解BeanFactory有助于理解 Spring 容器的底层实现原理。

综上所述,Spring 容器的创建方式多样,类层次结构丰富,BeanFactory是其核心基础,不同的容器和接口适用于不同的应用场景。



三、Bean 的概念

在 Spring 中,Bean 指的是由 Spring 容器管理的对象。这些对象的创建、初始化、销毁等生命周期过程都由 Spring 容器负责。Spring 容器会根据配置信息(可以是 XML 配置、注解配置或者 Java 代码配置)来创建和管理 Bean,开发者只需关注业务逻辑的实现,而无需手动管理对象的生命周期。

1. Bean 的配置

在 Spring 里,对 Bean 进行配置主要有三种常见方式,分别是 XML 配置、注解配置和 Java 配置。

XML 配置

借助 XML 文件来定义和配置 Bean,这是早期 Spring 开发常用的手段。以下是一个简单的示例:

XML 复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 定义一个名为userService的Bean -->
    <bean id="userService" class="com.example.service.UserService">
        <!-- 注入依赖 -->
        <property name="userRepository" ref="userRepository"/>
    </bean>

    <!-- 定义一个名为userRepository的Bean -->
    <bean id="userRepository" class="com.example.repository.UserRepository"/>
</beans>
注解配置

利用注解在类上直接标记 Bean,能够简化配置流程。常见的注解有@Component@Service@Repository@Controller等。

java 复制代码
import org.springframework.stereotype.Service;

@Service
public class UserService {
    // 业务逻辑代码
}

同时,还需要在配置类里启用组件扫描:

java 复制代码
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // 配置类代码
}
Java 配置

运用 Java 代码来配置 Bean,这种方式更加灵活。

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService();
    }

    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
}

2. Bean 的作用范围的配置

Spring 为 Bean 提供了多种作用范围,可通过scope属性或者@Scope注解来进行配置。

singleton(单例)

这是 Spring 默认的作用范围整个应用程序中只会创建一个 Bean 实例。

XML 复制代码
<bean id="userService" class="com.example.service.UserService" scope="singleton"/>

使用注解的方式:

java 复制代码
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service
@Scope("singleton")
public class UserService {
    // 业务逻辑代码
}
prototype(原型)

每次请求该 Bean 时,都会创建一个新的实例。

XML 复制代码
<bean id="userService" class="com.example.service.UserService" scope="prototype"/>

注解方式:

java 复制代码
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service
@Scope("prototype")
public class UserService {
    // 业务逻辑代码
}
request、session、application(仅适用于 Web 应用)
  • request:每个 HTTP 请求都会创建一个新的 Bean 实例。
  • session:每个 HTTP 会话会创建一个新的 Bean 实例。
  • application:整个 Web 应用程序中只会创建一个 Bean 实例。

3. Bean 的实例化(创建)

方式一:构造器实例化

Spring 默认会通过 Bean 类的无参构造器来创建实例。

java 复制代码
public class UserService {
    public UserService() {
        // 构造器代码
    }
}
方式二:静态工厂

使用静态工厂方法来创建 Bean 实例。

java 复制代码
public class UserServiceFactory {
    public static UserService createUserService() {
        return new UserService();
    }
}

XML 配置如下:

XML 复制代码
<bean id="userService" class="com.example.factory.UserServiceFactory" factory-method="createUserService"/>
方式三:实例工厂

先创建工厂类的实例,再通过该实例的方法创建 Bean。

java 复制代码
public class UserServiceInstanceFactory {
    public UserService createUserService() {
        return new UserService();
    }
}

XML 配置:

XML 复制代码
<bean id="userServiceFactory" class="com.example.factory.UserServiceInstanceFactory"/>
<bean id="userService" factory-bean="userServiceFactory" factory-method="createUserService"/>
方式四:方式三的优化(重点)

使用@Bean注解在配置类中创建 Bean,这种方式结合了 Java 配置的灵活性。

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public UserServiceInstanceFactory userServiceInstanceFactory() {
        return new UserServiceInstanceFactory();
    }

    @Bean
    public UserService userService() {
        return userServiceInstanceFactory().createUserService();
    }
}

4. Bean 的生命周期(从创建到销毁)

Bean 的生命周期包含实例化、属性赋值、初始化、使用和销毁这几个阶段。

初始化方法

可以通过实现InitializingBean接口的afterPropertiesSet方法、使用**@PostConstruct**注解或者在 XML 中配置init-method属性来指定初始化方法。

java 复制代码
import javax.annotation.PostConstruct;

public class UserService {
    @PostConstruct
    public void init() {
        // 初始化代码
    }
}
销毁方法

可通过实现DisposableBean接口的destroy方法、使用@PreDestroy注解或者在 XML 中配置destroy-method属性来指定销毁方法。

解决 Destroy 方法未执行的问题

如果Destroy方法没有执行,通常是因为 JVM 虚拟机在执行该方法前关闭了。可以通过以下两种方式解决:

  • 修改ApplicationContext接口,并调用close()方法关闭容器:
java 复制代码
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        // 使用Bean
        ctx.close(); // 关闭容器,触发销毁方法
    }
}
  • 使用registerShutdownHook()方法:
java 复制代码
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        ctx.registerShutdownHook(); // 注册关闭钩子,JVM关闭时触发销毁方法
        // 使用Bean
    }
}

在实际开发的 Web 应用中,通常不需要手动编写这些代码,因为随着 Tomcat 等服务器的关闭,Spring 容器会自动关闭,从而触发 Bean 的销毁方法。

综上所述,理解 Bean 的配置、作用范围、实例化方式以及生命周期,对于使用 Spring 框架进行开发至关重要。


四、IOC的实现方式-依赖注入(DI, Dependency Injection)

DI(Dependency Injection,依赖注入)是实现 IOC(控制反转)的关键技术,它描述了容器在创建对象时,将对象所依赖的其他对象传递给该对象的过程。以下结合你提供的图片内容进行详细讲解:

依赖注入方式

setter 注入

通过对象的 setter 方法来注入依赖。它允许在对象创建后再设置其依赖关系,较为灵活。

  • 简单类型:对于像基本数据类型(如 int、String 等 ),可以在配置文件中直接指定值。例如在 XML 配置里:
XML 复制代码
<bean id="user" class="com.example.User">
    <property name="name" value="张三"/>
</bean>

这里通过 property 标签,利用 User 类的 setName 方法将字符串 "张三" 注入。

  • 引用类型 :针对对象类型的依赖,比如一个 UserService 依赖 UserRepository ,配置如下:
XML 复制代码
<bean id="userRepository" class="com.example.UserRepository"/>
<bean id="userService" class="com.example.UserService">
    <property name="userRepository" ref="userRepository"/>
</bean>

上述配置会调用 UserServicesetUserRepository 方法,将 userRepository 实例注入。

构造器注入

在对象创建时,通过构造函数来注入依赖。构造器注入能确保依赖在对象创建时就已存在且不可变,增强了对象的稳定性。

  • 简单类型:若一个类的构造函数接收基本数据类型参数,在 XML 中配置如下:
XML 复制代码
<bean id="order" class="com.example.Order">
    <constructor - arg value="100"/>
</bean>

假设 Order 类有个构造函数 public Order(int amount) ,这里就会通过该构造函数将值 100 注入。

  • 引用类型 :当类依赖其他对象时,例如 ProductService 依赖 ProductRepository ,且通过构造函数注入:
XML 复制代码
<bean id="productRepository" class="com.example.ProductRepository"/>
<bean id="productService" class="com.example.ProductService">
    <constructor - arg ref="productRepository"/>
</bean>

即调用 ProductService 合适的构造函数(如 public ProductService(ProductRepository productRepository) ) 进行注入。

依赖注入方式选择

  • 建议使用 setter 注入:因为它的灵活性高,对象创建后还能修改依赖关系,适用于依赖关系多变的场景。比如某些配置信息可能在运行时动态改变,使用 setter 注入就可以方便地重新设置。
  • 第三方技术根据情况选择 :对于一些第三方类库,如果其构造函数已经被设计用于特定的初始化逻辑,可能构造器注入更合适;若第三方类库后续需要动态调整依赖,setter 注入会是更好的选择。

依赖自动装配

这是 IoC 容器自动处理依赖注入的机制,容器会根据 bean 所依赖的资源在容器中自动查找并注入到 bean 中。

  • 按类型(常用) :容器在查找依赖时,会依据依赖对象的类型在容器中寻找匹配的 Bean 进行注入。例如一个类依赖 UserRepository ,容器会查找类型为 UserRepository 的 Bean 注入。如果容器中存在多个同类型的 Bean ,会出现歧义,需要额外处理(比如结合 @Primary 注解指定首选 Bean )。
  • 按名称 :根据依赖对象的名称来查找匹配的 Bean 注入。在 XML 配置中可通过 autowire - by - name 开启,在注解方式中,@Resource 注解默认按名称装配(若未指定名称则按类型 )。
  • 按构造方法:容器会查找与目标类构造函数参数类型匹配的 Bean 进行注入,主要用于构造器注入场景下的自动装配。
  • 不启用自动装配:即不使用自动装配功能,开发者需完全显式地在配置文件或代码中指定依赖注入关系。

加载 properties 文件

在实际开发中,常需要从外部配置文件(.properties 文件 )读取配置信息并注入到 Bean 中,具体操作如下:

  • 开启 context 命名空间:在 XML 配置文件中,引入 Spring 的 context 命名空间,以便使用相关标签。示例如下:
XML 复制代码
<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
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
  • 使用 context 命名空间,加载指定 properties 文件 :通过 <context:property - placeholder> 标签加载指定的 .properties 文件,例如:
XML 复制代码
<context:property - placeholder location="jdbc.properties"/>

这会加载类路径下名为 jdbc.properties 的文件。

  • ** 使用\({}读取加载的属性值**:在配置 Bean 属性值时,可通过 `\){属性名}` 的方式读取已加载文件中的属性值,如:
XML 复制代码
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
</bean>

此外,还可以通过不同配置实现不加载系统属性(system - properties - mode="NEVER" )、加载多个 .properties 文件(以逗号分隔文件路径 )、加载所有 .properties 文件(使用通配符 )等功能。


五、配置方式对比

1. XML 配置(传统)
XML 复制代码
<bean id="userService" class="com.example.UserService">
    <property name="userDao" ref="userDao"/>
</bean>

运行 HTML

  • 缺点:冗长,类型不安全,维护成本高。
2. 注解配置(现代 Spring 主流)

通过注解简化配置,结合组件扫描实现自动化管理。


六、注解配置详解(重点)

Spring 框架里基于注解的配置,涵盖注解开发定义 Bean、Bean 管理、依赖注入、加载 properties 文件以及管理第三方 Bean 等方面。

1. 注解开发定义 Bean

在 Spring 里,@Component 注解可把一个类标记成 Spring Bean,让 Spring 容器能够对其进行管理。此外,Spring 还提供了功能和 @Component 一样的三个注解,分别是 @Repository@Service@Controller。这些注解在语义上有所区别,分别用于不同的层:

  • @Repository:一般用在数据访问层(DAO 层),代表这是一个数据仓库类。
  • @Service:常用于业务逻辑层(Service 层),代表这是一个业务服务类。
  • @Controller:一般用于表现层(Controller 层),代表这是一个控制器类。

下面是示例代码:

java 复制代码
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.stereotype.Controller;

// 数据访问层
@Repository
public class UserDao {
    public void saveUser() {
        System.out.println("Save user to database");
    }
}

// 业务逻辑层
@Service
public class UserService {
    private UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public void addUser() {
        userDao.saveUser();
    }
}

// 表现层
@Controller
public class UserController {
    private UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void handleUserRequest() {
        userService.addUser();
    }
}

2. 注解开发 - Bean 管理

依赖注入

依赖注入指的是把一个 Bean 注入到另一个 Bean 里。在 Spring 中,可使用 @Autowired 注解来达成依赖注入。@Autowired 注解能用在构造函数、setter 方法或者字段上。

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private UserDao userDao;

    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public void addUser() {
        userDao.saveUser();
    }
}
加载 properties 文件

要加载 properties 文件,可使用 @PropertySource 注解和 @Value 注解。@PropertySource 注解用于指定 properties 文件的位置,@Value 注解用于注入 properties 文件里的属性值。

java 复制代码
import org.springframework.context.annotation.PropertySource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
@PropertySource("classpath:config.properties")
public class AppConfig {
    @Value("${database.url}")
    private String databaseUrl;

    @Value("${database.username}")
    private String databaseUsername;

    @Value("${database.password}")
    private String databasePassword;

    public String getDatabaseUrl() {
        return databaseUrl;
    }

    public String getDatabaseUsername() {
        return databaseUsername;
    }

    public String getDatabasePassword() {
        return databasePassword;
    }
}
管理第三方 Bean

对于第三方库的 Bean,你可以编写一个方法来获取第三方 Bean,并且用 @Bean 注解把返回值设置成 Bean。

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class AppConfig {
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }
}

3. 纯注解开发配置类

要实现纯注解开发,你需要创建一个配置类,用 @Configuration 注解标记该类,同时用 @ComponentScan 注解开启组件扫描。

java 复制代码
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.example.demo")
public class AppConfig {
    // 配置类中的其他配置
}

4. 测试代码

以下是一个简单的测试代码,展示如何使用上述配置:

java 复制代码
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserController userController = context.getBean(UserController.class);
        userController.handleUserRequest();
        AppConfig appConfig = context.getBean(AppConfig.class);
        System.out.println("Database URL: " + appConfig.getDatabaseUrl());
        ObjectMapper objectMapper = context.getBean(ObjectMapper.class);
        System.out.println("ObjectMapper: " + objectMapper);
        context.close();
    }
}

小结

  • 运用 @Component@Repository@Service@Controller 注解定义 Bean。
  • 借助 @Autowired 注解实现依赖注入。
  • 利用 @PropertySource@Value 注解加载 properties 文件。
  • 使用 @Bean 注解管理第三方 Bean。
  • 采用 @Configuration@ComponentScan 注解实现纯注解开发。
注解配置 vs XML 配置
特性 注解配置 XML 配置
可读性 代码内嵌,直观 外部文件,需上下文切换
灵活性 强类型,编译时检查 字符串配置,易出错
维护性 修改代码需重新编译 动态修改无需编译
适用场景 现代 Spring Boot 项目 遗留系统或复杂配置

总结

Spring 的 IOC 容器 通过注解配置(如 @Component, @Autowired, @Configuration)实现了轻量级、高内聚的依赖管理。注解配置已成为现代 Spring 开发的主流方式,兼顾灵活性和代码简洁性,是 Spring Boot 自动配置的基石。

相关推荐
JavaPub-rodert1 分钟前
一道go面试题
开发语言·后端·golang
6<74 分钟前
【go】静态类型与动态类型
开发语言·后端·golang
柚几哥哥5 分钟前
IntelliJ IDEA全栈Git指南:从零构建到高效协作开发
java·git·intellij-idea
技术liul9 分钟前
解决Spring Boot Configuration Annotation Processor not configured
java·spring boot·后端
chushiyunen21 分钟前
dom操作笔记、xml和document等
xml·java·笔记
whisperrr.21 分钟前
【spring01】Spring 管理 Bean-IOC,基于 XML 配置 bean
xml·java·spring
chushiyunen24 分钟前
tomcat使用笔记、启动失败但是未打印日志
java·笔记·tomcat
天上掉下来个程小白30 分钟前
HttpClient-03.入门案例-发送POST方式请求
java·spring·httpclient·苍穹外卖
ModestCoder_40 分钟前
将一个新的机器人模型导入最新版isaacLab进行训练(以unitree H1_2为例)
android·java·机器人
a180079310801 小时前
软件工程面试题(二十二)
java·面试·软件工程