Spring Bean工厂原理与类关系详解
一、核心概念
1.1 Bean
Bean是由Spring容器管理的对象,可以是任何Java类的实例。Spring容器负责Bean的创建、初始化、配置和管理生命周期。
1.2 Bean工厂
Bean工厂(BeanFactory)是Spring框架中负责创建和管理Bean的核心组件,主要职责包括:
- 管理Bean的定义信息
- 创建Bean实例
- 管理Bean的生命周期
- 处理Bean之间的依赖关系
1.3 Bean定义
BeanDefinition是描述Bean元数据信息的对象,包含创建Bean所需的所有信息:
- Bean的类型(Class)
- Bean的作用域(单例、原型等)
- Bean的初始化方法
- Bean的销毁方法
- Bean的依赖关系
二、核心接口与类
2.1 BeanFactory接口
BeanFactory是Bean工厂的顶级接口,定义了获取Bean的基本方法。
public interface BeanFactory {
Object getBean(String beanName) throws BeansException;
Object getBean(String beanName, Object... args) throws BeansException;
}
2.2 BeanDefinition类
BeanDefinition类定义了Bean的元数据信息。
public class BeanDefinition {
private Class beanClass;
public BeanDefinition(Class beanClass) {
this.beanClass = beanClass;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
}
2.3 BeansException类
BeansException是Spring中处理Bean相关异常的基类。
public class BeansException extends RuntimeException {
public BeansException() {
super();
}
public BeansException(String message) {
super(message);
}
public BeansException(String message, Throwable cause) {
super(message, cause);
}
}
三、实现类详解
3.1 DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistry是SingletonBeanRegistry接口的默认实现,使用HashMap存储单例Bean实例。
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private Map<String, Object> singletonObjects = new HashMap<>();
@Override
public void registerSingleton(String beanName, Object singleton) {
singletonObjects.put(beanName, singleton);
}
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
}
3.2 AbstractBeanFactory
AbstractBeanFactory是BeanFactory接口的抽象实现,继承自DefaultSingletonBeanRegistry。它实现了Bean的获取逻辑,管理单例Bean的缓存,并定义了创建Bean的抽象方法。
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String beanName) throws BeansException {
Object singleton = getSingleton(beanName);
if (singleton != null) {
return singleton;
}
BeanDefinition beanDefinition = getBeanDefinition(beanName);
return createBean(beanName, beanDefinition);
}
@Override
public Object getBean(String beanName, Object... args) throws BeansException {
Object singleton = getSingleton(beanName);
if (singleton != null) {
return singleton;
}
BeanDefinition beanDefinition = getBeanDefinition(beanName);
return createBean(beanName, beanDefinition, args);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object... args) throws BeansException;
}
3.3 AbstractAutowireCapableBeanFactory
AbstractAutowireCapableBeanFactory实现了创建Bean的具体逻辑,使用InstantiationStrategy接口来创建Bean实例。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
private InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
return createBean(beanName, beanDefinition, null);
}
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object... args) throws BeansException {
Object bean = null;
try {
bean = createBeanInstance(beanDefinition, beanName, args);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
registerSingleton(beanName, bean);
return bean;
}
protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object... args) throws BeansException {
Constructor constructor = null;
Class<?> beanClass = beanDefinition.getBeanClass();
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
for (Constructor<?> ctor : declaredConstructors) {
if (args != null && ctor.getParameterTypes().length == args.length) {
constructor = ctor;
break;
}
}
return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructor, args);
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
}
3.4 DefaultListableBeanFactory
DefaultListableBeanFactory是Spring Bean工厂的核心实现类,实现了BeanDefinitionRegistry接口和继承了AbstractAutowireCapableBeanFactory。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new BeansException("No bean named '" + beanName + "' is defined");
}
return beanDefinition;
}
}
3.5 InstantiationStrategy接口及实现
InstantiationStrategy接口定义了Bean实例化的策略,有两个实现类:
SimpleInstantiationStrategy:使用Java反射机制创建Bean实例。
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
Class<?> beanClass = beanDefinition.getBeanClass();
try {
if (ctor != null) {
return beanClass.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
} else {
return beanClass.getDeclaredConstructor().newInstance();
}
} catch (Exception e) {
throw new BeansException("Failed to instantiate [" + beanClass.getName() + "]", e);
}
}
}
CglibInstantiationStrategy:使用Cglib库创建Bean实例,支持更复杂的场景。
public class CglibInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
try {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setCallback(new NoOp() {
@Override
public int hashCode() {
return super.hashCode();
}
});
if (ctor != null) {
return enhancer.create(ctor.getParameterTypes(), args);
} else {
return enhancer.create();
}
} catch (Exception e) {
throw new BeansException("Failed to instantiate [" + beanDefinition.getBeanClass().getName() + "]", e);
}
}
}
四、类关系图
4.1 继承关系
BeanFactory
↑
AbstractBeanFactory
↑
AbstractAutowireCapableBeanFactory
↑
DefaultListableBeanFactory
DefaultSingletonBeanRegistry
↑
AbstractBeanFactory
4.2 实现关系
- DefaultListableBeanFactory implements BeanDefinitionRegistry
- DefaultSingletonBeanRegistry implements SingletonBeanRegistry
- SimpleInstantiationStrategy implements InstantiationStrategy
- CglibInstantiationStrategy implements InstantiationStrategy
4.3 组合关系
- AbstractAutowireCapableBeanFactory组合了InstantiationStrategy
- DefaultListableBeanFactory组合了BeanDefinition的存储
五、Bean生命周期
5.1 生命周期阶段
- Bean定义阶段:通过BeanDefinition描述Bean的元数据信息
- Bean注册阶段:将BeanDefinition注册到BeanDefinitionRegistry中
- Bean实例化阶段:根据BeanDefinition创建Bean实例
- Bean初始化阶段:对Bean实例进行初始化,如设置属性、处理依赖注入等
- Bean使用阶段:Bean实例被应用程序使用
- Bean销毁阶段:Bean实例被销毁(单例Bean)
5.2 实例化策略
- 使用无参构造函数:如果Bean类有无参构造函数,直接使用反射创建实例
- 使用带参构造函数:如果Bean类只有带参构造函数,使用反射或Cglib创建实例
- 使用工厂方法:通过指定的工厂方法创建实例
- 使用工厂Bean:通过实现FactoryBean接口的Bean创建实例
六、Bean作用域
6.1 单例作用域(Singleton)
Spring的默认作用域,一个Bean定义在Spring容器中只会创建一个实例,所有对该Bean的请求都会返回同一个实例。
优点 :节省内存、提高性能、共享状态
缺点:线程安全问题、状态管理复杂
6.2 原型作用域(Prototype)
每次请求Bean时都会创建一个新的实例,适用于需要频繁创建和销毁的对象。
优点 :线程安全、状态隔离
缺点:内存消耗大、性能较低
6.3 Web应用作用域
- Request:每个HTTP请求创建一个新的Bean实例
- Session:每个HTTP会话创建一个新的Bean实例
- GlobalSession:每个全局HTTP会话创建一个新的Bean实例(Portlet应用)
七、依赖注入
7.1 构造函数注入
通过Bean的构造函数来注入依赖关系。
public class UserService {
private final UserDao userDao;
@Autowired
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
优点:确保Bean在创建时就拥有所有必要的依赖、避免了循环依赖、提高了代码的可读性和可测试性
7.2 Setter方法注入
通过Bean的Setter方法来注入依赖关系。
public class UserService {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
优点:支持可选依赖、支持依赖的动态修改、简化了单元测试
7.3 字段注入
通过注解直接注入到Bean的字段中。
public class UserService {
@Autowired
private UserDao userDao;
}
优点 :代码简洁、减少了样板代码
缺点:破坏了封装性、使依赖关系不明确、难以进行单元测试
八、自动装配
8.1 自动装配模式
- no:默认值,不进行自动装配
- byName:根据属性名称自动装配
- byType:根据属性类型自动装配
- constructor:根据构造函数参数类型自动装配
- autodetect:自动检测使用constructor或byType模式
8.2 优缺点
优点 :减少手动配置的工作量、提高配置的可读性和可维护性、减少配置错误的可能性
缺点:依赖关系不够明确、可能导致意外的依赖注入、不支持复杂的依赖关系
九、工作原理
9.1 初始化阶段
- 加载配置:Spring容器加载配置文件或注解,解析Bean定义
- 注册Bean定义:将解析后的Bean定义注册到BeanDefinitionRegistry中
- 初始化单例Bean:对于单例作用域的Bean,在容器启动时就创建实例
9.2 获取Bean阶段
- 检查缓存:首先检查单例缓存中是否存在Bean实例
- 创建Bean :如果缓存中不存在,则创建Bean实例
- 获取Bean定义
- 实例化Bean
- 初始化Bean
- 缓存单例Bean
- 返回Bean:返回Bean实例给调用者
9.3 销毁阶段
- 关闭容器:当应用程序关闭时,关闭Spring容器
- 销毁单例Bean:调用单例Bean的销毁方法
十、应用示例
10.1 基本使用
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
10.2 带参数的构造函数
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = new BeanDefinition(UserServiceWithConstructor.class);
beanFactory.registerBeanDefinition("userServiceWithConstructor", beanDefinition);
UserServiceWithConstructor userService = (UserServiceWithConstructor) beanFactory.getBean("userServiceWithConstructor", "test", 25);
userService.queryUserInfo();
10.3 使用不同的实例化策略
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
((AbstractAutowireCapableBeanFactory) beanFactory).setInstantiationStrategy(new CglibInstantiationStrategy());
BeanDefinition beanDefinition = new BeanDefinition(UserServiceWithConstructor.class);
beanFactory.registerBeanDefinition("userServiceWithConstructor", beanDefinition);
UserServiceWithConstructor userService = (UserServiceWithConstructor) beanFactory.getBean("userServiceWithConstructor", "test", 25);
userService.queryUserInfo();
十一、扩展点
11.1 自定义BeanPostProcessor
允许在Bean初始化前后对Bean进行处理。
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Before initialization: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("After initialization: " + beanName);
return bean;
}
}
11.2 自定义FactoryBean
允许自定义Bean的创建过程。
public class MyFactoryBean implements FactoryBean<UserService> {
@Override
public UserService getObject() throws Exception {
return new UserService();
}
@Override
public Class<?> getObjectType() {
return UserService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
11.3 自定义InstantiationStrategy
允许自定义Bean的实例化策略。
public class MyInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
System.out.println("Instantiating bean: " + beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
try {
if (ctor != null) {
return beanClass.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
} else {
return beanClass.getDeclaredConstructor().newInstance();
}
} catch (Exception e) {
throw new BeansException("Failed to instantiate [" + beanClass.getName() + "]", e);
}
}
}
十二、最佳实践
12.1 使用注解配置
注解配置更加简洁、直观。
@Component
public class UserService {
}
@Configuration
@ComponentScan("com.example")
public class AppConfig {
}
12.2 合理使用作用域
- 对于无状态的Bean,使用单例作用域
- 对于有状态的Bean,使用原型作用域
- 对于Web应用,根据需要使用request、session等作用域
12.3 避免循环依赖
循环依赖是指两个或多个Bean之间相互依赖,Spring可以处理构造函数注入以外的循环依赖,但最好避免。
12.4 使用构造函数注入
构造函数注入是Spring推荐的依赖注入方式,它可以确保Bean在创建时就拥有所有必要的依赖。
12.5 使用@Qualifier注解
当存在多个同类型的Bean时,使用@Qualifier注解指定要注入的Bean名称。
@Component
public class UserService {
private final UserDao userDao;
@Autowired
public UserService(@Qualifier("userDaoImpl") UserDao userDao) {
this.userDao = userDao;
}
}
12.6 使用@Value注解
使用@Value注解注入配置值,提高配置的灵活性。
@Component
public class UserService {
@Value("${user.service.name}")
private String name;
}
十三、常见问题与解决方案
13.1 NoSuchBeanDefinitionException
原因 :找不到指定名称的Bean定义
解决方案:检查Bean名称是否正确、检查Bean是否已注册、检查配置是否正确
13.2 BeanCreationException
原因 :Bean创建失败
解决方案:检查Bean的构造函数是否正确、检查Bean的依赖是否存在、检查Bean的初始化方法是否正确
13.3 UnsatisfiedDependencyException
原因 :依赖注入失败
解决方案:检查依赖的Bean是否存在、检查依赖的类型是否匹配、检查自动装配的配置是否正确
13.4 CircularDependencyException
原因 :循环依赖
解决方案:重构代码消除循环依赖、使用Setter方法注入代替构造函数注入、使用@Lazy注解延迟加载
13.5 NoClassDefFoundError
原因 :找不到类定义
解决方案:检查依赖是否正确、检查类路径是否正确、检查版本是否兼容
13.6 IllegalArgumentException
原因 :参数非法
解决方案:检查方法参数是否正确、检查配置值是否正确、检查Bean定义是否正确
十四、总结
Spring Bean工厂是Spring框架的核心组件,它通过管理Bean的定义、创建和生命周期,为应用程序提供了一种灵活、可配置的对象管理机制。
核心优势:
- 灵活性:支持多种配置方式和实例化策略
- 可扩展性:提供了丰富的扩展点
- 可靠性:成熟稳定的实现
- 易用性:简洁直观的API
通过理解Spring Bean工厂的原理和类与类之间的关系,开发者可以更好地掌握Spring框架的工作机制,构建高质量的应用程序。作为开发者,我们应该不断学习和掌握Spring框架的新特性和最佳实践,以提高开发效率和代码质量。