网站采集功能,工作人员否认陈道明演庆余年2,自己做的网站出现乱码,请问那个网站做推广好点从零手写Spring IoC容器#xff08;二#xff09;#xff1a;bean的定义与注册
一. 回顾简单容器的不足之处
在第一章中#xff0c;我们实现了一个最简单的 IoC 容器#xff0c;但该版本存在诸多不足#xff0c;例如#xff1a;
Bean 的管理方式过于简单#xff0c;…从零手写Spring IoC容器二bean的定义与注册
一. 回顾简单容器的不足之处
在第一章中我们实现了一个最简单的 IoC 容器但该版本存在诸多不足例如
Bean 的管理方式过于简单无法描述 Bean 之间的依赖关系。缺少 Bean 作用域的管理无法区分单例singleton和原型prototype。无法设置 Bean 的属性不能进行依赖注入。没有生命周期管理无法进行初始化与销毁操作。
为了克服上述缺陷我们需要引入 Bean 的定义与注册机制。
二. 问题分析
1. 如何描述 Bean
为了更灵活地管理 Bean我们需要对其进行更详细的描述
类信息Bean 的具体实现类配置信息属性值、环境相关配置依赖关系需要注入哪些其他 Bean
2. 如何管理 Bean 的定义
IoC 容器不仅需要存储 Bean还需要提供完善的管理机制
统一注册机制能够注册、移除、获取 Bean 定义。运行时切换支持不同的 Bean 作用域例如单例singleton或原型prototype。依赖分析和注入支持属性注入确保 Bean 能够正确构造。
三. 设计 BeanDefinition
我们先设计 BeanDefinition 接口来描述 Bean
包含 Bean 的完整信息支持属性配置支持作用域管理支持生命周期方法
1.设计BeanDefinition 接口
package com.fth.beans.factory.config;/*** 用于描述 Bean 的定义*/
public interface BeanDefinition {// Bean 作用域常量String SCOPE_SINGLETON singleton;String SCOPE_PROTOTYPE prototype;// 基本信息void setBeanClass(Class? beanClass);Class? getBeanClass();// 作用域void setScope(String scope);String getScope();boolean isSingleton();boolean isPrototype();// 是否延迟初始化void setLazyInit(boolean lazyInit);boolean isLazyInit();// 生命周期方法void setInitMethodName(String initMethodName);String getInitMethodName();void setDestroyMethodName(String destroyMethodName);String getDestroyMethodName();// 属性void setPropertyValues(PropertyValues propertyValues);PropertyValues getPropertyValues();
}
2. PropertyValue 和 PropertyValues
PropertyValue 用于存储单个 Bean 属性的信息而 PropertyValues 作为容器存储 Bean 的所有属性。
package com.fth.beans.factory.config;/*** Bean 属性值的封装类*/
public class PropertyValue {private final String name;private final Object value;private final Class? type;/*** 创建一个新的 PropertyValue 实例*/public PropertyValue(String name, Object value, Class? type) {if (name null || name.isEmpty()) {throw new IllegalArgumentException(Property name must not be null or empty);}this.name name;this.value value;this.type type;}/*** 不指定类型的 PropertyValue 构造方法*/public PropertyValue(String name, Object value) {this(name, value, value ! null ? value.getClass() : Object.class);}public String getName() {return this.name;}public Object getValue() {return this.value;}public Class? getType() {return this.type;}Overridepublic boolean equals(Object other) {if (this other) {return true;}if (!(other instanceof PropertyValue)) {return false;}return this.name.equals(((PropertyValue) other).name);}Overridepublic int hashCode() {return this.name.hashCode();}Overridepublic String toString() {return PropertyValue: name this.name , value[ this.value ];}
}
3.实现BeanDefinition
GenericBeanDefinition 是 BeanDefinition 的一个具体实现用于存储 Bean 的元数据。
package com.fth.beans.factory.support;import com.fth.beans.factory.config.BeanDefinition;
import com.fth.beans.factory.config.PropertyValues;/*** 通用 BeanDefinition 实现*/
public class GenericBeanDefinition implements BeanDefinition {private Class? beanClass;private String scope SCOPE_SINGLETON;private boolean lazyInit false;private String initMethodName;private String destroyMethodName;private PropertyValues propertyValues new PropertyValues();Overridepublic void setBeanClass(Class? beanClass) {this.beanClass beanClass;}Overridepublic Class? getBeanClass() {return this.beanClass;}Overridepublic void setScope(String scope) {this.scope scope;}Overridepublic String getScope() {return this.scope;}Overridepublic boolean isSingleton() {return SCOPE_SINGLETON.equals(this.scope);}Overridepublic boolean isPrototype() {return SCOPE_PROTOTYPE.equals(this.scope);}Overridepublic void setLazyInit(boolean lazyInit) {this.lazyInit lazyInit;}Overridepublic boolean isLazyInit() {return this.lazyInit;}Overridepublic void setInitMethodName(String initMethodName) {this.initMethodName initMethodName;}Overridepublic String getInitMethodName() {return this.initMethodName;}Overridepublic void setDestroyMethodName(String destroyMethodName) {this.destroyMethodName destroyMethodName;}Overridepublic String getDestroyMethodName() {return this.destroyMethodName;}Overridepublic void setPropertyValues(PropertyValues propertyValues) {this.propertyValues propertyValues;}Overridepublic PropertyValues getPropertyValues() {return this.propertyValues;}
}
四. 设计 BeanDefinitionRegistry
为了注册和管理 Bean 定义我们设计 BeanDefinitionRegistry 接口
package com.fth.beans.factory.support;import com.fth.beans.factory.config.BeanDefinition;/*** BeanDefinition 注册表*/
public interface BeanDefinitionRegistry {void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);void removeBeanDefinition(String beanName);BeanDefinition getBeanDefinition(String beanName);boolean containsBeanDefinition(String beanName);String[] getBeanDefinitionNames();int getBeanDefinitionCount();
}
五.实现第二版 IoC 容器
我们现在基于 BeanDefinition 和 BeanDefinitionRegistry 来实现一个基本的 IoC 容器支持手动注册 BeanDefinition并能够根据 BeanDefinition 创建 Bean 实例同时支持 单例 和 原型 两种作用域。
1. 设计 DefaultBeanFactory
DefaultBeanFactory 负责
维护 BeanDefinition 的注册表根据 BeanDefinition 创建 Bean处理单例和原型作用域
package com.fth.beans.factory.support;import com.fth.beans.BeansException;
import com.fth.beans.factory.BeanFactory;
import com.fth.beans.factory.config.BeanDefinition;
import com.fth.beans.factory.config.BeanDefinitionRegistry;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 默认 Bean 工厂负责管理 BeanDefinition 和 Bean 实例*/
public class DefaultBeanFactory implements BeanDefinitionRegistry, BeanFactory {// 存储 BeanDefinitionprivate final MapString, BeanDefinition beanDefinitionMap new ConcurrentHashMap();// 存储单例 Beanprivate final MapString, Object singletonObjects new ConcurrentHashMap();// 实现 BeanDefinitionRegistry Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {beanDefinitionMap.put(beanName, beanDefinition);// 如果是单例且非懒加载则立即创建实例if (beanDefinition.isSingleton() !beanDefinition.isLazyInit()) {singletonObjects.put(beanName, createBean(beanDefinition));}}Overridepublic void removeBeanDefinition(String beanName) {beanDefinitionMap.remove(beanName);singletonObjects.remove(beanName);}Overridepublic BeanDefinition getBeanDefinition(String beanName) {return beanDefinitionMap.get(beanName);}Overridepublic boolean containsBeanDefinition(String beanName) {return beanDefinitionMap.containsKey(beanName);}Overridepublic String[] getBeanDefinitionNames() {return beanDefinitionMap.keySet().toArray(new String[0]);}Overridepublic int getBeanDefinitionCount() {return beanDefinitionMap.size();}// 实现 BeanFactory Overridepublic Object getBean(String name) throws BeansException {BeanDefinition beanDefinition getBeanDefinition(name);if (beanDefinition null) {throw new BeansException(No bean named name is defined);}if (beanDefinition.isSingleton()) {return singletonObjects.computeIfAbsent(name, k - createBean(beanDefinition));}return createBean(beanDefinition);}Overridepublic T T getBean(String name, ClassT requiredType) throws BeansException {Object bean getBean(name);if (!requiredType.isInstance(bean)) {throw new BeansException(Bean named name is not of type requiredType.getName());}return requiredType.cast(bean);}Overridepublic T T getBean(ClassT requiredType) throws BeansException {for (String beanName : beanDefinitionMap.keySet()) {Object bean getBean(beanName);if (requiredType.isInstance(bean)) {return requiredType.cast(bean);}}throw new BeansException(No bean of type requiredType.getName() is defined);}Overridepublic boolean containsBean(String name) {return beanDefinitionMap.containsKey(name);}Overridepublic boolean isSingleton(String name) throws BeansException {BeanDefinition beanDefinition getBeanDefinition(name);return beanDefinition ! null beanDefinition.isSingleton();}Overridepublic boolean isPrototype(String name) throws BeansException {BeanDefinition beanDefinition getBeanDefinition(name);return beanDefinition ! null beanDefinition.isPrototype();}Overridepublic Class? getType(String name) throws BeansException {BeanDefinition beanDefinition getBeanDefinition(name);return (beanDefinition ! null) ? beanDefinition.getBeanClass() : null;}/*** 根据 BeanDefinition 创建 Bean 实例*/private Object createBean(BeanDefinition beanDefinition) {try {// 获取无参构造函数Constructor? constructor beanDefinition.getBeanClass().getDeclaredConstructor();constructor.setAccessible(true); // 设置可访问return constructor.newInstance(); // 使用构造函数创建实例} catch (Exception e) {throw new RuntimeException(Failed to create bean: beanDefinition.getBeanClass(), e);}}
}
2.测试使用
package com.fth.test;import com.fth.beans.factory.BeanFactory;
import com.fth.beans.factory.support.DefaultBeanFactory;
import com.fth.beans.factory.support.GenericBeanDefinition;/*** 测试 IoC 容器*/
public class BeanFactoryTest {public static void main(String[] args) {// 创建 BeanFactoryDefaultBeanFactory beanFactory new DefaultBeanFactory();// 注册一个单例 BeanGenericBeanDefinition singletonDefinition new GenericBeanDefinition();singletonDefinition.setBeanClass(TestService.class);singletonDefinition.setScope(GenericBeanDefinition.SCOPE_SINGLETON);beanFactory.registerBeanDefinition(testService, singletonDefinition);// 获取单例 BeanTestService service1 beanFactory.getBean(testService, TestService.class);TestService service2 beanFactory.getBean(testService, TestService.class);System.out.println(service1 service2: (service1 service2)); // true// 注册一个原型 BeanGenericBeanDefinition prototypeDefinition new GenericBeanDefinition();prototypeDefinition.setBeanClass(TestService.class);prototypeDefinition.setScope(GenericBeanDefinition.SCOPE_PROTOTYPE);beanFactory.registerBeanDefinition(prototypeService, prototypeDefinition);// 获取原型 BeanTestService proto1 beanFactory.getBean(prototypeService, TestService.class);TestService proto2 beanFactory.getBean(prototypeService, TestService.class);System.out.println(proto1 proto2: (proto1 proto2)); // false}
}/*** 测试用 Bean*/
class TestService {public void sayHello() {System.out.println(Hello from TestService!);}
}
六.与Spring的对比与下一步实现
与Spring的对比
1. Bean 的注册与获取
Spring: Spring 使用 ApplicationContext 来管理 Bean。Bean 的定义可以通过注解、XML 配置或者 Java 配置类来进行。ApplicationContext 允许根据名称或类型来获取 Bean并且支持 Bean 的自动装配。 自定义 IoC 容器: 在自定义容器中我们通过手动注册 BeanDefinition 和 BeanFactory 来管理 Bean。目前的实现只能通过名称获取单个 Bean且只支持单例和原型的基本功能。
2. Bean 的生命周期管理
Spring: Spring 提供了丰富的生命周期管理功能例如 初始化方法支持 PostConstruct 注解、init-method 属性等。销毁方法支持 PreDestroy 注解、destroy-method 属性等。BeanPostProcessor可以在 Bean 初始化前后执行特定操作。ApplicationContextAware、BeanFactoryAware 等使 Bean 可以访问容器的相关信息。 自定义 IoC 容器: 当前实现没有处理 Bean 的初始化、销毁等生命周期管理功能相对简单主要关注 Bean 的创建和作用域单例、原型。
3. 作用域管理
Spring: Spring 支持多种作用域包括 singleton默认每个 Bean 在容器中只有一个实例。prototype每次请求都会返回一个新的 Bean 实例。request, session, application 等在 Web 环境下Spring 支持更多基于 HTTP 请求的作用域。 自定义 IoC 容器: 当前实现仅支持 singleton 和 prototype 两种作用域。
4. 自动装配与依赖注入
Spring: Spring 支持基于注解如 Autowired和 XML 配置的自动装配。可以自动解析 Bean 之间的依赖关系通过构造函数、Setter 或字段注入方式注入依赖。 自定义 IoC 容器: 当前版本没有实现依赖注入和自动装配需要手动处理 Bean 的依赖关系。
下一步安排Bean 的生命周期管理
为了让自定义的 IoC 容器更加完善下一步实现 Bean 的生命周期管理这包括以下几个方面
1. 初始化与销毁
初始化方法可以为每个 Bean 定义一个初始化方法在 Bean 创建后、依赖注入完成后执行。销毁方法可以为每个 Bean 定义销毁方法在 Bean 被销毁前执行释放资源。
2. 添加 BeanPostProcessor 机制
Spring 提供了 BeanPostProcessor 接口允许开发者在 Bean 初始化前后执行特定操作。你可以在自定义容器中实现类似机制
初始化前在 Bean 实例化后、依赖注入前执行。初始化后在 Bean 初始化完成后执行。 文章转载自: http://www.morning.spghj.cn.gov.cn.spghj.cn http://www.morning.wfkbk.cn.gov.cn.wfkbk.cn http://www.morning.ppqjh.cn.gov.cn.ppqjh.cn http://www.morning.tymwx.cn.gov.cn.tymwx.cn http://www.morning.ljjph.cn.gov.cn.ljjph.cn http://www.morning.fkgqn.cn.gov.cn.fkgqn.cn http://www.morning.rkqzx.cn.gov.cn.rkqzx.cn http://www.morning.dxtxk.cn.gov.cn.dxtxk.cn http://www.morning.hbpjb.cn.gov.cn.hbpjb.cn http://www.morning.pdgqf.cn.gov.cn.pdgqf.cn http://www.morning.rfmzc.cn.gov.cn.rfmzc.cn http://www.morning.jbhhj.cn.gov.cn.jbhhj.cn http://www.morning.lrnfn.cn.gov.cn.lrnfn.cn http://www.morning.bmgdl.cn.gov.cn.bmgdl.cn http://www.morning.iznek.com.gov.cn.iznek.com http://www.morning.rxwfg.cn.gov.cn.rxwfg.cn http://www.morning.lwlnw.cn.gov.cn.lwlnw.cn http://www.morning.lqtwb.cn.gov.cn.lqtwb.cn http://www.morning.gxwyr.cn.gov.cn.gxwyr.cn http://www.morning.kpbq.cn.gov.cn.kpbq.cn http://www.morning.ykshx.cn.gov.cn.ykshx.cn http://www.morning.fqlxg.cn.gov.cn.fqlxg.cn http://www.morning.geledi.com.gov.cn.geledi.com http://www.morning.hlnrj.cn.gov.cn.hlnrj.cn http://www.morning.ykwbx.cn.gov.cn.ykwbx.cn http://www.morning.rfhm.cn.gov.cn.rfhm.cn http://www.morning.jgnst.cn.gov.cn.jgnst.cn http://www.morning.thzwj.cn.gov.cn.thzwj.cn http://www.morning.lpqgq.cn.gov.cn.lpqgq.cn http://www.morning.rdxnt.cn.gov.cn.rdxnt.cn http://www.morning.rsxw.cn.gov.cn.rsxw.cn http://www.morning.dztp.cn.gov.cn.dztp.cn http://www.morning.pszw.cn.gov.cn.pszw.cn http://www.morning.pzpj.cn.gov.cn.pzpj.cn http://www.morning.tnjz.cn.gov.cn.tnjz.cn http://www.morning.rfrxt.cn.gov.cn.rfrxt.cn http://www.morning.hrgxk.cn.gov.cn.hrgxk.cn http://www.morning.nqmwk.cn.gov.cn.nqmwk.cn http://www.morning.jrdbq.cn.gov.cn.jrdbq.cn http://www.morning.bnfrj.cn.gov.cn.bnfrj.cn http://www.morning.zqmdn.cn.gov.cn.zqmdn.cn http://www.morning.ldcrh.cn.gov.cn.ldcrh.cn http://www.morning.rqwwm.cn.gov.cn.rqwwm.cn http://www.morning.ssxlt.cn.gov.cn.ssxlt.cn http://www.morning.gyxwh.cn.gov.cn.gyxwh.cn http://www.morning.errnull.com.gov.cn.errnull.com http://www.morning.wwsgl.com.gov.cn.wwsgl.com http://www.morning.dlurfdo.cn.gov.cn.dlurfdo.cn http://www.morning.hqlnp.cn.gov.cn.hqlnp.cn http://www.morning.rbnnq.cn.gov.cn.rbnnq.cn http://www.morning.brwwr.cn.gov.cn.brwwr.cn http://www.morning.cbpkr.cn.gov.cn.cbpkr.cn http://www.morning.webife.com.gov.cn.webife.com http://www.morning.ymdhq.cn.gov.cn.ymdhq.cn http://www.morning.zmnyj.cn.gov.cn.zmnyj.cn http://www.morning.nqcwz.cn.gov.cn.nqcwz.cn http://www.morning.wnnts.cn.gov.cn.wnnts.cn http://www.morning.smpb.cn.gov.cn.smpb.cn http://www.morning.stsnf.cn.gov.cn.stsnf.cn http://www.morning.mftdq.cn.gov.cn.mftdq.cn http://www.morning.cpzkq.cn.gov.cn.cpzkq.cn http://www.morning.mwlxk.cn.gov.cn.mwlxk.cn http://www.morning.qzxb.cn.gov.cn.qzxb.cn http://www.morning.lpgw.cn.gov.cn.lpgw.cn http://www.morning.mtcnl.cn.gov.cn.mtcnl.cn http://www.morning.ksggr.cn.gov.cn.ksggr.cn http://www.morning.zdydj.cn.gov.cn.zdydj.cn http://www.morning.xtxp.cn.gov.cn.xtxp.cn http://www.morning.rydhq.cn.gov.cn.rydhq.cn http://www.morning.jpbpc.cn.gov.cn.jpbpc.cn http://www.morning.bxqry.cn.gov.cn.bxqry.cn http://www.morning.yfstt.cn.gov.cn.yfstt.cn http://www.morning.pwghp.cn.gov.cn.pwghp.cn http://www.morning.ghyfm.cn.gov.cn.ghyfm.cn http://www.morning.ryyjw.cn.gov.cn.ryyjw.cn http://www.morning.ltspm.cn.gov.cn.ltspm.cn http://www.morning.ywndg.cn.gov.cn.ywndg.cn http://www.morning.bqxxq.cn.gov.cn.bqxxq.cn http://www.morning.bkkgt.cn.gov.cn.bkkgt.cn http://www.morning.xhgxd.cn.gov.cn.xhgxd.cn