zoukankan      html  css  js  c++  java
  • 自己动手写spring(四) 整合xml与注解方式

    前言

    本文总结前文的内容,将两种方式整合在一起。

    再次强调,要实现bean工厂功能,首先要将bean信息加载到内存,由配置文件或注解方式转化为“以类的方式”存储,并以map的形式组织起来(为方便查询)。具体的说就是

    public class BeanFactory {
    	private Beans beans;
    	// 实现id到bean对象的映射
    	private Map<String,Bean> beanId2Bean = new HashMap<String,Bean>();
    	// 实现id到clazz的映射
    	private Map<String,Class> beanId2Clazz = new HashMap<String,Class>();
    	
    	// 实现id到对象的映射,保存创建好的bean实例
    	private Map<String, Object> beanId2Class = new HashMap<String, Object>();
    	
    	public BeanFactory() {
    		try {
    			loadXml();
    			loadAnnotation();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	// getBean时,先尝试从xml中获取一下,如果没有,再尝试从注解信息中获取一下  	
        public Object getBean(String beanId) throws Exception{
    		Object obj = beanId2Class.get(beanId);
    		if (obj != null) {
    			return obj;
    		}	
    		obj = getBeanFromXml(beanId);
    		if(obj == null){
    			obj = getBeanFromAnnotation(beanId);
    		}
    		if (obj != null) {
    			beanId2Class.put(beanId, obj);
    		}
    	    return obj;
        }
    }
    

    代码中的loadXml,loadAnnotation,getBeanFromXml,getBeanFromAnnotation可从前文的load和getBean方法中得到。

    增加tag类

    前文中,扫描使用注解类的包的包名是写死在代码中,此处将其写在配置文件中。为此,要调整一些标签类(省略get和set方法)。

    // 添加scan类
    public class Scan {
    	private String packageName;	
    }
    调整Beans类
    public class Beans {
    	private List<Bean> beans = new ArrayList<Bean>();
    	// 事实上可能有多个scan,但多个scan类已不是难点所在,此处不再赘述
    	private Scan scan;
    }
    // beans.xml配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
    	<bean id="beanA" name="test" class="org.lqk.lspring1.bean.BeanA">
    		<property name="beanB" ref="beanB"/>
    		<property name="title" value="studentA"/>
    	</bean>
    	<scan package="org.lqk.lspring1.bean"/>
    </beans>
    

    到此为止了么?

    在示例中,beanA使用了xml文件方式,beanB使用了注解方式,BeanFactory正常工作啦。但旋即,笔者注意到一个问题,粒度。目前的粒度,是以Bean为单位,一个Bean要么全注解方式,要么全配置文件方式。但经常使用spring的人,会知道有一种情况:在配置文件中声明bean,然后在类中使用@autowire注入属性,因此我们要调整getBean方法。

    public Object getBean(String beanId) throws Exception{
    	Object obj = beanId2Class.get(beanId);
    	if (obj != null) {
    		return obj;
    	}	
    	// 此处,不再一判空就返回
    	obj = getBeanFromXml(beanId);
    	obj = getBeanFromAnnotation(beanId);
    	return obj;
    }
    
    public Object getBeanFromAnnotation(String beanId) throws Exception{
    	Class clazz = beanId2Clazz.get(beanId);
    	if(null == clazz){
    		return null;
    	}
    	Object obj = beanId2Class.get(beanId);
    	// getBeanFromXml没有构建该bean时,创建bean。否则,复用bean。
    	if (obj == null) {
    		obj = clazz.newInstance();
    	}
    	// 省略前文中getBean代码
    }	
    

    其它

    到这里,我们就实现了spring的基本功能之一,依赖注入。其实主要就是两个步骤:

    1. 将元信息从配置文件和注解中加载到类中
    2. 根据元信息,使用反射构建bean

    当然,按照代码重构的逻辑,BeanFactory的很多方法,可以独立为一个组件,这样BeanFactory就不会很臃肿。

    在下文中,我们将提供对bean生命周期的管理。

  • 相关阅读:
    手把手教你安装系统-只需一个U盘
    Linux系统优化05-Centos修改主机名
    Linux系统优化06-Centos远程登录与连接(SSH配置)
    数据库ACID
    Java中的String,StringBuilder,StringBuffer三者的区别
    zookeeper的选举机制
    mysql的数据类型
    常用类(四)
    常用类(三)
    常用类(二)
  • 原文地址:https://www.cnblogs.com/qiankunli/p/4947438.html
Copyright © 2011-2022 走看看