Spring 如何管理 bean

本文转载自:https://blog.csdn.net/l18848956739/article/details/80917853

常常听老师说容器,容器是什么?Spring 中是如何体现的?一直有疑惑,这两天看了一下Spring 管理 bean 的 Demo,对于 Spring 中的容器有了简单的认识。

本文只是对 bean 的一个超级简单的理解,实际 Spring 中的 bean 复杂多了

我们知道,容器是一个空间的概念,一般理解为可盛放物体的地方。在 Spring 容器通常理解为 BeanFactory 或者 ApplicationContext。我们知道 Spring 的 IoC 容器能够帮我们创建对象,对象交给 Spring 管理之后我们就不用手动去 new 对象。


BeanFactory 与 ApplicationContext 的区别是什么?

  • BeanFactory 采用了工厂设计模式,负责读取 bean 配置文档,管理 bean 的加载,实例化,维护 bean 之间的依赖关系,负责 bean 的声明周期
  • ApplicationContext 除了提供上述 BeanFactory 所能提供的功能之外,还提供了更完整的框架功能:国际化支持、AOP、事务等
  • BeanFactory 在解析配置文件时并不会初始化对象,只有在使用对象 getBean() 才会对该对象进行初始化,而 ApplicationContext 在解析配置文件时对配置文件中的所有对象都初始化了,getBean() 方法只是获取对象的过程。

ApplicationContext 是如何管理 Bean 呢?下面这个 Demo 简单模仿了这个原理:

建立一个类PersonServiceBean,并在xml文件中进行配置

public class PersonServiceBean implements PersonService   {  
    public void save(){  
        System.out.println("我是save()方法");  
    }  
}  
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean> 

建立类BeanDefinition,提供一个构造函数,将其作为每个bean的公共转型类

public class BeanDefinition {  
      
    private String id;    
    private String className;  
      
    public BeanDefinition(String id, String className) {  
        this.id = id;  
        this.className = className;  
    }  
  
    public String getId() {  
        return id;  
    }  
  
    public void setId(String id) {  
        this.id = id;  
    }  
  
    public String getClassName() {  
        return className;  
    }  
  
    public void setClassName(String className) {  
        this.className = className;  
    }  
}  

建立容器类 tgbApplicationContext

/** 
 * 测试spring容器 
 * @author hegang 
 * 
 */  
public class tgbClassPathXMLApplicationContext {  
      
    private List<BeanDefinition> beanDefines =new ArrayList<BeanDefinition>();  
    private Map<String,Object> sigletons =new HashMap<String,Object>();  
      
      
    public tgbClassPathXMLApplicationContext(String filename){  
        this.readXML(filename);  
        this.instanceBeans();  
    }  
  
    /** 
     * 完成bean的实例化 
     */  
    private void instanceBeans() {  
        for(BeanDefinition beanDefinition :  beanDefines){  
            try {  
                if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim())){  
                  sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance());  
                }  
            } catch (Exception e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
              
        }  
          
    }  
  
    /** 
     * 读取xml配置文件 
     * @param filename 
     */  
    private void readXML(String filename) {  
        SAXReader saxReader = new SAXReader(); //创建读取器  
        Document document =null;  
        try{  
            URL xmlpath = this.getClass().getClassLoader().getResource(filename);  
            document =saxReader.read(xmlpath);  
            Map<String,String> nsMap =new HashMap<String,String>();  
            nsMap.put("ns","http://www.springframework.org/schema/beans"); //加入命名空间  
            XPath xsub = document.createXPath("//ns:beans/ns:bean"); //创建beans/bean查询路径  
             xsub.setNamespaceURIs(nsMap); // 设置命名空间  
            List<Element> beans = xsub.selectNodes(document); // 获取文档下所有的bean节点  
            for(Element element:beans){  
                String id =element.attributeValue("id"); // 获取id属性值  
                String clazz =element.attributeValue("class"); // 获取class属性值  
                BeanDefinition beanDefine =new BeanDefinition(id,clazz);  
                beanDefines.add(beanDefine);  
            }  
          
        } catch(Exception e){  
            e.printStackTrace();  
        }  
          
    }  
      
    /** 
     * 获取bean实例 
     * @param beanName 
     * @return 
     */  
    public Object getBean(String beanName){  
        return this.sigletons.get(beanName);  
    }  
}  

该类中拥有一个 List<BeanDefinition> 泛型集合类以及一个 Map<String,Object> 集合。通过查看代码我们知道这个容器类所做的事情如下:

  • 读取配置文件 bean.xml,并根据文件中 bean 的 id, class 属性实例化一个 BeanDefinition,装入泛型集合中
  • 通过循环+反射,将 List<BeanDefinition> 中的 bean 加入到 Map<String,Object> 中,这里用反射将 bean 中的 className 属性转换为一个实例化的 bean 对象加入到了 Map 中
  • 提供一个对外的接口,通过传入参数获取该 bean

下面就是通过容器类获取具体 bean 的代码了

public class SpringTest {  
    @Test  
    public void instanceSpring(){  
        tgbClassPathXMLApplicationContext ctx =new tgbClassPathXMLApplicationContext("beans.xml");    
        PersonService personService =(PersonService) ctx.getBean("personService");  
        personService.save();  
    }  
}

通过这样的 Demo,可以清楚看到 Spring 容器做的事情。它在初始化的时候将配置文件中 bean 以及相对应关系的配置都加入到 ApplicationContext,通过一系列的转换将这些 bean 实例化,bean 被它进行了管理,所以 ApplicationContext 就扮演了一个容器的角色。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值