Spring容器的本质
什么是Spring容器?
Spring容器本质上是一个对象工厂,它负责创建、配置和管理应用程序中的对象(称为Bean)。容器是Spring框架的核心,所有的Spring功能都基于容器实现。
注意:这里说的 【 创建、配置、管理 】应用程序中的对象,应该深刻理解。# 【附录】举例说明Spring是如何进行 创建、配置和管理 对象的呢?
容器的核心作用
- 对象创建: 负责创建应用程序中需要的所有对象
- 依赖管理: 自动注入对象之间的依赖关系
- 生命周期管理: 管理对象的创建、初始化、使用和销毁
- 配置管理: 统一管理对象的配置信息
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 - 高级容器
ApplicationContext
是BeanFactory
的子接口,提供了更多企业级功能:
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的后处理机制
容器的出发点:
- 解决传统Java开发的耦合问题
- 实现控制反转(IoC)
- 提供统一的配置管理
- 支持面向切面编程(AOP)
容器的优势:
- 松耦合
- 可扩展性
- 可测试性
- 可维护性
Spring容器通过统一的对象管理机制,大大简化了Java企业级应用的开发,提高了代码的质量和可维护性。