Spring 容器详解

Spring容器的本质

什么是Spring容器?

Spring容器本质上是一个对象工厂,它负责创建、配置和管理应用程序中的对象(称为Bean)。容器是Spring框架的核心,所有的Spring功能都基于容器实现。

注意:这里说的 【 创建、配置、管理 】应用程序中的对象,应该深刻理解。# 【附录】举例说明Spring是如何进行 创建、配置和管理 对象的呢?

容器的核心作用

  1. 对象创建: 负责创建应用程序中需要的所有对象
  2. 依赖管理: 自动注入对象之间的依赖关系
  3. 生命周期管理: 管理对象的创建、初始化、使用和销毁
  4. 配置管理: 统一管理对象的配置信息

Spring容器的构成

注意:这里说的 Spring容器 为 BeanFactory和ApplicationContext,需要思考,他们并没有用于储存bean的map或者list,为什么说他们是 spring的容器?【附录】为什么说BeanFactory和ApplicationContext是Spring容器?

1. BeanFactory - 基础容器

BeanFactory是Spring容器的基础接口,提供了最基本的IoC功能:

java 复制代码
public interface BeanFactory {
    // 根据名称获取Bean
    Object getBean(String name);
    
    // 根据类型获取Bean
    <T> T getBean(Class<T> requiredType);
    
    // 根据名称和类型获取Bean
    <T> T getBean(String name, Class<T> requiredType);
    
    // 检查Bean是否存在
    boolean containsBean(String name);
    
    // 检查Bean是否为单例
    boolean isSingleton(String name);
    
    // 获取Bean的类型
    Class<?> getType(String name);
}

BeanFactory的特点:

  • 延迟加载:只有在请求Bean时才创建
  • 功能简单:只提供基本的IoC功能
  • 轻量级:占用资源少

2. ApplicationContext - 高级容器

ApplicationContextBeanFactory的子接口,提供了更多企业级功能:

java 复制代码
public interface ApplicationContext extends BeanFactory {
    // 获取应用名称
    String getApplicationName();
    
    // 获取启动时间
    long getStartupDate();
    
    // 获取父容器
    ApplicationContext getParent();
    
    // 获取环境信息
    Environment getEnvironment();
    
    // 发布事件
    void publishEvent(ApplicationEvent event);
    
    // 获取资源
    Resource getResource(String location);
}

ApplicationContext的特点:

  • 预加载:启动时就创建所有单例Bean
  • 功能丰富:支持AOP、事件、国际化等
  • 企业级:适合生产环境使用

3. 容器的核心组件

这里主要是归纳了,Spring容器中收纳的bean,以及对Bean进行更改的通用方法

BeanDefinition - Bean定义

spring环境中 的BeanDefinition 来源是由哪些?如何理解 BeanDefinition ,他在spring中起到了什么作用?解释点这里

java 复制代码
public interface BeanDefinition {
    // Bean的类名
    void setBeanClassName(String beanClassName);
    String getBeanClassName();
    
    // Bean的作用域
    void setScope(String scope);
    String getScope();
    
    // 是否懒加载
    void setLazyInit(boolean lazyInit);
    boolean isLazyInit();
    
    // 依赖的Bean
    void setDependsOn(String... dependsOn);
    String[] getDependsOn();
    
    // 初始化方法
    void setInitMethodName(String initMethodName);
    String getInitMethodName();
    
    // 销毁方法
    void setDestroyMethodName(String destroyMethodName);
    String getDestroyMethodName();
}

BeanPostProcessor - Bean后处理器

BeanPostProcessor有不同的实现,不同的实现在功能上会有所不同,即在增强或改变bean的时间节点会有所不同,增强或改变的逻辑也有所不同。解释点这里

java 复制代码
public interface BeanPostProcessor {
    // Bean初始化前的处理
    Object postProcessBeforeInitialization(Object bean, String beanName);
    
    // Bean初始化后的处理
    Object postProcessAfterInitialization(Object bean, String beanName);
}

BeanFactoryPostProcessor - 工厂后处理器

BeanFactoryPostProcessor与上面的BeanPostProcessor 所增强的对象会有所不同。解释点这里

java 复制代码
public interface BeanFactoryPostProcessor {
    // 在BeanFactory初始化后,Bean实例化前调用
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}

Spring容器的实现类

这里只针对容器这一块来说明,是BeanFactory和ApplicationContext 的不同实现类,主要用在不同的场景下。

1. ClassPathXmlApplicationContext

java 复制代码
// 基于XML配置的容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean(UserService.class);

2. AnnotationConfigApplicationContext

java 复制代码
// 基于注解配置的容器
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);

3. FileSystemXmlApplicationContext

java 复制代码
// 基于文件系统XML配置的容器
ApplicationContext context = new FileSystemXmlApplicationContext("C:/config/applicationContext.xml");

4. WebApplicationContext

java 复制代码
// Web应用专用的容器
// 在Spring MVC中使用

Spring容器的启动过程

注意:这里所有的容器启动,其实都是基于main方法的。不同的容器实现类,读取bean的方式不同,但最终都要进行context.refresh();即刷新容器,刷新容器有12大步骤。解释点这里

1. 容器初始化阶段

java 复制代码
// 1. 创建容器实例
ApplicationContext context = new AnnotationConfigApplicationContext();

// 2. 注册配置类
context.register(AppConfig.class);

// 3. 刷新容器
context.refresh();

2. Bean定义加载阶段

注意:bean加载阶段比较复杂,需要新的篇章来解释。解释点这里

java 复制代码
// 1. 扫描配置类
// 2. 解析@Bean注解
// 3. 扫描@Component等注解
// 4. 创建BeanDefinition

3. Bean实例化阶段

注意:bean的实例化阶段比较复杂,需要新的篇章来解释。解释点这里

java 复制代码
// 1. 创建Bean实例
// 2. 注入依赖
// 3. 调用初始化方法
// 4. 注册到容器

Spring容器的诞生是为了解决什么问题

1. 解决传统Java开发的问题

传统方式的问题:

java 复制代码
// 硬编码依赖,耦合度高
public class UserService {
    private UserDao userDao = new UserDaoImpl();
    private EmailService emailService = new EmailServiceImpl();
    
    public void registerUser(User user) {
        userDao.save(user);
        emailService.sendWelcomeEmail(user);
    }
}

Spring容器解决的问题:

java 复制代码
// 依赖由容器管理,松耦合
@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    
    @Autowired
    private EmailService emailService;
    
    public void registerUser(User user) {
        userDao.save(user);
        emailService.sendWelcomeEmail(user);
    }
}

2. 实现控制反转(IoC)

传统方式:

  • 对象自己创建依赖
  • 对象自己管理生命周期
  • 对象之间耦合度高

Spring容器方式:

  • 容器负责创建对象
  • 容器负责注入依赖
  • 容器管理对象生命周期
  • 对象之间松耦合

3. 提供统一的配置管理

传统方式:

java 复制代码
// 配置分散在各个类中
public class UserDaoImpl implements UserDao {
    private String url = "jdbc:mysql://localhost:3306/test";
    private String username = "root";
    private String password = "123456";
}

Spring容器方式:

java 复制代码
// 统一配置管理
@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(
            "jdbc:mysql://localhost:3306/test",
            "root",
            "123456"
        );
    }
}

4. 支持面向切面编程(AOP)

java 复制代码
// 通过容器实现AOP
@Component
public class LoggingAspect {
    @Around("@annotation(Loggable)")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("方法开始执行: " + joinPoint.getSignature());
        Object result = joinPoint.proceed();
        System.out.println("方法执行完成: " + joinPoint.getSignature());
        return result;
    }
}

容器的设计模式

1. 工厂模式

java 复制代码
// 容器作为对象工厂
public class BeanFactory {
    public Object getBean(String name) {
        // 创建和管理Bean
    }
}

2. 单例模式

java 复制代码
// 容器管理单例Bean
public class SingletonBeanRegistry {
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }
}

3. 观察者模式

java 复制代码
// 容器支持事件机制
public class ApplicationEventMulticaster {
    public void multicastEvent(ApplicationEvent event) {
        // 发布事件给所有监听器
    }
}

容器的优势

1. 松耦合

  • 对象之间不直接依赖
  • 通过接口进行交互
  • 易于测试和维护

2. 可扩展性

  • 易于添加新功能
  • 支持插件式架构
  • 支持热插拔

3. 可测试性

  • 易于进行单元测试
  • 支持Mock对象
  • 支持测试隔离

4. 可维护性

  • 统一的配置管理
  • 清晰的依赖关系
  • 易于问题排查

总结

Spring容器是Spring框架的核心,它的本质是一个对象工厂,负责创建、配置和管理应用程序中的对象。

容器的构成:

  • BeanFactory:基础容器,提供基本IoC功能
  • ApplicationContext:高级容器,提供企业级功能
  • BeanDefinition:Bean的定义信息
  • BeanPostProcessor:Bean的后处理机制

容器的出发点:

  1. 解决传统Java开发的耦合问题
  2. 实现控制反转(IoC)
  3. 提供统一的配置管理
  4. 支持面向切面编程(AOP)

容器的优势:

  • 松耦合
  • 可扩展性
  • 可测试性
  • 可维护性

Spring容器通过统一的对象管理机制,大大简化了Java企业级应用的开发,提高了代码的质量和可维护性。

相关推荐
Dcr_stephen3 分钟前
Spring 事务中的 beforeCommit 是业务救星还是地雷?
后端
raoxiaoya10 分钟前
Golang中的`io.Copy()`使用场景
开发语言·后端·golang
二闹16 分钟前
高效开发秘籍:CRUD增强实战
后端·设计模式·性能优化
我爱娃哈哈16 分钟前
Eureka vs Consul,服务注册发现到底选哪个?性能对比深度解析!
后端
肆伍佰17 分钟前
iOS应用混淆技术详解
后端
xiaok18 分钟前
将dify部署到服务器上
后端
00后程序员18 分钟前
移动端 WebView 调试实战 深色模式样式失效与主题切换异常排查指南
后端
程序员清风27 分钟前
Context7 MCP,让Cursor告别代码幻觉!
java·后端·面试
dylan_QAQ42 分钟前
【附录】BeanFactoryPostProcessor的作用时机与核心实现?
后端·spring
熊猫片沃子1 小时前
MyBatis 中 where1=1 一些替换方式
java·后端·mybatis