开发中某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。这个过程是怎么实现的,下面就bean.xml文件中的<bean/>做简要分析。
<bean id=“model” class=“com.shc.ModelFrog”>这个配置代表了一个bean,项目启动后它在spring容器中充当一个对象。<bean/>是在项目启动的时候被加入到spring容器中的,究竟是如何加载进去的?想必大家都熟悉java bean,他是一种规范,spring正是利用这种规范完成了依赖注入的过程。项目启动之初,Spring框架通过反射根据<bean.../>元素的class属性指定的类名(以反射方式来调用该类无参数的构造器)创建了一个Java对象,并以<bean.../>元素的id属性的值为key,将该对象放入Spring容器中—这个对象就成了Spring容器中的Bean。这个bean在spring容器中的存储方式类似于map集合,map<key,bean>,之所以说bean是单例的,因为key是唯一的。
ModelFrog”(解析<bean.../>元素的class属性得到的值)。
以上过程在Spring底层执行的代码过程如下所示:
String idStr=“model”;//解析该<bean.../>元素的id属性得到该字符串值为“model”
//解析<bean.../>元素的class属性得到的值为”com.shc.ModelFrog”
String classStr =“com.shc.ModelFrog”;
Class clazz = Class.forName(classStr);
Object obj = class.newInstance();
//Container代表的Spring容器
container.put(idStr,obj);
如何完成依赖注入?举例如下
<bean id=“model” class=“com.shc.ModelFrog”>
//控制调用setGuagua()方法,将容器中的guagua Bean作为传入的参数
<property name=“wa” ref=“guagua”/>
</bean>
<bean id=“guagua” class=“com.shc.GuaGua”><bean id=“wuwu” class=“com.shc.WuWu”>
上面配置文件中包含一个<property。。。/>子元素,<property.../>子元素通常用于作为<bean.../>元素的子元素,它驱动Spring在底层以反射执行一次setter方法。其中<property。。。/>的name属性值决定执行那个setter方法,而value或者ref决定执行setter方法的传入参数。
1.如果传入参数是基本类型及其包装类、String等类型,则使用value属性指定传入的参数。
2.如果以容器中其他的Bean作为传入参数,则使用ref属性指定传入参数。
该Bean一旦创建处理,Spring会立即根据<property。。。/>子元素来执行setter方法。即:<bean.../>元素驱动Spring调用构造器创建对象;<property。。。/>子元素驱动Spring执行setter方法,这两个步骤是先后执行的,中间几乎没有时间间隔。
以上过程在Spring底层会执行如下代码:
String nameStr =“guagua”;//解析<property。。。/>元素的name属性得到该字符串的值为“guagua”
String refStr=“guagua”;//解析<property。。。/>元素的ref属性得到该字符串的值为“guagua”。
String setterName=“set”+nameStr.substring(0,1).toUpperCase()+nameStr.subString(1);//生成将要调用的setter方法名。
//获取Spring容器中名为refStr的Bean,该Bean将会作为传入参数。
Object paramBean = container.get(refStr);
//此处的clazz是前一段反射代码通过<bean.../>元素的class属性得到的.Class对象
Method setter = clazz.getMethod(setterName, paramBean.getClass());
//此处的obj参数是前一段反射代码为<bean.../>元素创建的对象
setter.invoke(obj, paramBean);
如果此时修改<property name=“wa” ref=“guagua”/>中ref="wuwu",那注入的类将会是WuWu