Spring系列二:基础篇(2)

```
  • BeanRegister.java

    对象注册器,这里用于单例bean的缓存,我们大幅简化,默认所有bean都是单例的。可以看到所谓单例注册,也很简单,不过是往HashMap里存对象。

    
    public class BeanRegister {
    
    
    
        //单例Bean缓存
    
        private Map<String, 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);
    
        }
    
    
    
    }
    
    
    
    
  • BeanFactory.java

    BeanFactory

    • 对象工厂,我们最核心的一个类,在它初始化的时候,创建了bean注册器,完成了资源的加载。

    • 获取bean的时候,先从单例缓存中取,如果没有取到,就创建并注册一个bean

      
      public class BeanFactory {
      
      
      
          private Map<String, 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定义,创建bean
      
              return createBean(beanDefinitionMap.get(beanName));
      
          }
      
      
      
          /**
      
           * 创建Bean
      
           *
      
           * @param beanDefinition bean定义
      
           * @return
      
           */
      
          private Object createBean(BeanDefinition beanDefinition) {
      
              try {
      
                  Object bean = beanDefinition.getBeanClass().newInstance();
      
                  //缓存bean
      
                  beanRegister.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 {
      
          @Test
      
          public void test_BeanFactory() {
      
              //1.创建bean工厂(同时完成了加载资源、创建注册单例bean注册器的操作)
      
              BeanFactory beanFactory = new BeanFactory();
      
      
      
              //2.第一次获取bean(通过反射创建bean,缓存bean)
      
              UserDao userDao1 = (UserDao) beanFactory.getBean("userDao");
      
              userDao1.queryUserInfo();
      
      
      
              //3.第二次获取bean(从缓存中获取bean)
      
              UserDao userDao2 = (UserDao) beanFactory.getBean("userDao");
      
              userDao2.queryUserInfo();
      
          }
      
      }
      
      
      
      
    • 运行结果

      
      A good man.
      
      A good man.
      
      
      
      

至此,我们一个乞丐+破船版的Spring就完成了,代码也比较完整,有条件的可以跑一下。

PS:因为时间+篇幅的限制,这个demo比较简陋,没有面向接口、没有解耦、边界检查、异常处理……健壮性、扩展性都有很大的不足,感兴趣可以学习参考[15]。

7.说说BeanFactory和ApplicantContext?


可以这么形容,BeanFactory是Spring的“心脏”,ApplicantContext是完整的“身躯”。

BeanFactory和ApplicantContext的比喻

  • BeanFactory(Bean工厂)是Spring框架的基础设施,面向Spring本身。

  • ApplicantContext(应用上下文)建立在BeanFactoty基础上,面向使用Spring框架的开发者。

BeanFactory 接口

BeanFactory是类的通用工厂,可以创建并管理各种类的对象。

Spring为BeanFactory提供了很多种实现,最常用的是XmlBeanFactory,但在Spring 3.2中已被废弃,建议使用XmlBeanDefinitionReader、DefaultListableBeanFactory。

Spring5 BeanFactory继承体系

BeanFactory接口位于类结构树的顶端,它最主要的方法就是getBean(String var1),这个方法从容器中返回特定名称的Bean。

BeanFactory的功能通过其它的接口得到了不断的扩展,比如AbstractAutowireCapableBeanFactory定义了将容器中的Bean按照某种规则(比如按名字匹配、按类型匹配等)进行自动装配的方法。

这里看一个 XMLBeanFactory(已过期)  获取bean 的例子:


public class HelloWorldApp{ 

   public static void main(String[] args) { 

      BeanFactory factory = new XmlBeanFactory (new ClassPathResource("beans.xml")); 

      HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");    

      obj.getMessage();    

   }

}



ApplicationContext 接口

ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。可以这么说,使用BeanFactory就是手动档,使用ApplicationContext就是自动档。

Spring5 ApplicationContext部分体系类图

ApplicationContext 继承了HierachicalBeanFactory和ListableBeanFactory接口,在此基础上,还通过其他的接口扩展了BeanFactory的功能,包括:

  • Bean instantiation/wiring

  • Bean 的实例化/串联

  • 自动的 BeanPostProcessor 注册

  • 自动的 BeanFactoryPostProcessor 注册

  • 方便的 MessageSource 访问(i18n)

  • ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在 ApplicationContext 启动之后实例化

这是 ApplicationContext 的使用例子:


public class HelloWorldApp{ 

   public static void main(String[] args) { 

      ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); 

      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");    

      obj.getMessage();    

   }

}



ApplicationContext 包含 BeanFactory 的所有特性,通常推荐使用前者。

最后

这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档

祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!

感谢大家的支持!!

image.png

pp{

public static void main(String[] args) {

ApplicationContext context=new ClassPathXmlApplicationContext(“beans.xml”);

HelloWorld obj = (HelloWorld) context.getBean(“helloWorld”);

obj.getMessage();

}

}




ApplicationContext 包含 BeanFactory 的所有特性,通常推荐使用前者。




### 最后

**这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档**

祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!

感谢大家的支持!!

[外链图片转存中...(img-R040MOjX-1719175809712)]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值