电子商务网站策划书3000字,设计公司网站制作,网站如何不让百度抓取,里水九江网站建设Spring是我们最常用的开源框架#xff0c;经过多年发展#xff0c;Spring已经发展成枝繁叶茂的大树#xff0c;让我们难以窥其全貌。这节#xff0c;我们回归Spring的本质#xff0c;五分钟手撸一个Spring容器#xff0c;揭开Spring神秘的面纱#xff01;从什么是IOC开始… Spring是我们最常用的开源框架经过多年发展Spring已经发展成枝繁叶茂的大树让我们难以窥其全貌。这节我们回归Spring的本质五分钟手撸一个Spring容器揭开Spring神秘的面纱从什么是IOC开始Spring——春天Java编程世界的春天是由一位音乐家——Rod Johnson带来的。Rod Johnson先后编写了两本巨著《Expert One-on-One J2EE Design and Development》、《Expert One-on-One J2EE Development without EJB》拉起了挑战正统Java EE框架EJB的大旗。Rod Johnson两大著作-来自百度百科Rod Johnson不仅是一名旗手更是开发了Spring这一轻量级框架像一名勇敢的龙骑兵一样对EJB发动了冲锋并最终战胜了EJB让Spring成为Java EE事实上的标准。Spring LogoSpring的两大内核分别是IOC和AOP其中最最核心的是IOC。所谓的IOC控制反转就是由容器来负责控制对象的生命周期和对象间的关系。以前是我们想要什么就自己创建什么现在是我们需要什么容器就给我们送来什么。引入IOC之前和引入IOC之后也就是说控制对象生命周期的不再是引用它的对象而是容器。对具体对象以前是它控制其它对象现在所有对象都被容器控制所以这就叫控制反转。控制反转示意图也许你还听到另外一个概念DI依赖注入它指的是容器在实例化对象的时候把它依赖的类注入给它我们也可以认为DI是IOC的补充和实现。工厂和Spring容器Spring是一个成熟的框架为了满足扩展性、实现各种功能所以它的实现如同枝节交错的大树一样现在让我们把视线从Spring本身移开来看看一个萌芽版的Spring容器怎么实现。Spring的IOC本质就是一个大工厂我们想想一个工厂是怎么运行的呢工厂运行生产产品一个工厂最核心的功能就是生产产品。在Spring里不用Bean自己来实例化而是交给Spring应该怎么实现呢——答案毫无疑问反射。那么这个厂子的生产管理是怎么做的你应该也知道——工厂模式。库存产品工厂一般都是有库房的用来库存产品毕竟生产的产品不能立马就拉走。Spring我们都知道是一个容器这个容器里存的就是对象不能每次来取对象都得现场来反射创建对象得把创建出的对象存起来。订单处理还有最重要的一点工厂根据什么来提供产品呢订单。这些订单可能五花八门有线上签签的、有到工厂签的、还有工厂销售上门签的……最后经过处理指导工厂的出货。在Spring里也有这样的订单它就是我们bean的定义和依赖关系可以是xml形式也可以是我们最熟悉的注解形式。那对应我们的萌芽版的Spring容器是什么样的呢mini版本Spring IOC订单Bean定义Bean可以通过一个配置文件定义我们会把它解析成一个类型。Bean定义beans.properties为了偷懒这里直接用了最方便解析的properties用一个key,value类型的配置来代表Bean的定义其中key是beanNamevalue是classuserDao:cn.fighter3.bean.UserDaoBeanDefinition.javabean定义类配置文件中bean定义对应的实体public class BeanDefinition {private String beanName;private Class beanClass;//省略getter、setter }获取订单资源加载接下订单之后就要由销售向生产部门交接让生产部门知道商品的规格、数量之类。资源加载器就是来完成这个工作的由它来完成配置文件中配置的加载。public class ResourceLoader {public static MapString, BeanDefinition getResource() {MapString, BeanDefinition beanDefinitionMap new HashMap(16);Properties properties new Properties();try {InputStream inputStream ResourceLoader.class.getResourceAsStream(/beans.properties);properties.load(inputStream);IteratorString it properties.stringPropertyNames().iterator();while (it.hasNext()) {String key it.next();String className properties.getProperty(key);BeanDefinition beanDefinition new BeanDefinition();beanDefinition.setBeanName(key);Class clazz Class.forName(className);beanDefinition.setBeanClass(clazz);beanDefinitionMap.put(key, beanDefinition);}inputStream.close();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}return beanDefinitionMap;}}订单分配Bean注册对象注册器这里用于单例bean的缓存我们大幅简化默认所有bean都是单例的。可以看到所谓单例注册也很简单不过是往HashMap里存对象。public class BeanRegister {//单例Bean缓存private MapString, Object singletonMap new HashMap(32);/*** 获取单例Bean** param beanName bean名称* return*/public Object getSingletonBean(String beanName) {return singletonMap.get(beanName);}/*** 注册单例bean** param beanName* param bean*/public void registerSingletonBean(String beanName, Object bean) {if (singletonMap.containsKey(beanName)) {return;}singletonMap.put(beanName, bean);}}生产车间对象工厂好了到了我们最关键的生产部门了在工厂里生产产品的是车间在IOC容器里生产对象的是BeanFactory。BeanFactory对象工厂我们最核心的一个类在它初始化的时候创建了bean注册器完成了资源的加载。获取bean的时候先从单例缓存中取如果没有取到就创建并注册一个beanpublic class BeanFactory {private MapString, BeanDefinition beanDefinitionMap new HashMap();private BeanRegister beanRegister;public BeanFactory() {//创建bean注册器beanRegister new BeanRegister();//加载资源this.beanDefinitionMap new ResourceLoader().getResource();}/*** 获取bean** param beanName bean名称* return*/public Object getBean(String beanName) {//从bean缓存中取Object bean beanRegister.getSingletonBean(beanName);if (bean ! null) {return bean;}//根据bean定义创建beanreturn createBean(beanDefinitionMap.get(beanName));}/*** 创建Bean** param beanDefinition bean定义* return*/private Object createBean(BeanDefinition beanDefinition) {try {Object bean beanDefinition.getBeanClass().newInstance();//缓存beanbeanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);return bean;} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();}return null;}
}生产销售测试UserDao.java我们的Bean类很简单public class UserDao {public void queryUserInfo(){System.out.println(A good man.);}
}单元测试public class ApiTest {Testpublic void test_BeanFactory() {//1.创建bean工厂(同时完成了加载资源、创建注册单例bean注册器的操作)BeanFactory beanFactory new BeanFactory();//2.第一次获取bean通过反射创建bean缓存beanUserDao userDao1 (UserDao) beanFactory.getBean(userDao);userDao1.queryUserInfo();//3.第二次获取bean从缓存中获取beanUserDao userDao2 (UserDao) beanFactory.getBean(userDao);userDao2.queryUserInfo();}
}运行结果A good man.
A good man.至此我们一个萌芽版的Spring容器就完成了。考虑一下它有哪些不足呢是否还可以抽象、扩展、解耦……细细想想这些东西你是不是对真正的Spring IOC容器为何如此复杂有所理解了呢参考[1]. 《Spring揭秘》[2].小傅哥 《手撸Spring》[3].《精通Spring4.X企业应用开发实战》往期推荐Spring 夺命 35 问Spring Boot 优雅配置多数据源IDEA 版 Postman 面世了功能真心强大