先从网上分别找两个不同实现的配置
静态工厂注入
实例化静态工作注入
我来先来看看spring对工厂注入配置的解析.
在文件BeanDefinitionParserDelegate.java里面parseBeanDefinitionAttributes函数里
有这么两句话来解析xml配置,这个定义如下
CONSTRUCTOR_ARG_ELEMENT属性获取是在另外一个函数里,大家有兴趣自己去研究.大体就是在这里数据被解析并保存.
那么在getBean的时候这些数据就派上用场了.大体流程如下图
流程比较简单,一步一步来说下:
1.
doCreateBean这个函数就是用来创建并进行属性注入的地方.而createBeanInstance就是bean实例化的地方.来看createBeanInstance的实现.
2.看到高亮的没.if条件进行判断getFactoryMethodName是不是为空,实际上只要是工厂注入那么getFactoryMethodName一定不会为空.所以会走进去
3.再来看看instantiateUsingFactoryMethod的实现
这里只是作了一个中转调用.继续跟踪
4.instantiateUsingFactoryMethod
instantiateUsingFactoryMethod这个函数,实现体很长.在这里只截取头部.而头部也是静态工厂方法和实例工作方法最大区别的地方.
1)实例工作方法getFactoryBeanName是不为空的,所以会进入if语句块进行执行.
一.首先通过getBean方法调用生成工厂实例.factoryBean= new object();
2).静态工厂方法是没有getFactoryBeanName的,会走到else
一.静态工厂方法没有父类Bean可以依靠,所以必需有自己的class
二.factoryBean = null
instantiateUsingFactoryMethod剩余的代码两者是一样的处理过程.这个过程简单的来说如下:
1).拿到所有的工厂类的Method
2).从Method中找到配置的需要调用的method
3).从配置中拿到参数,然后进行相应的处理
最就是通过反射调用方法生成Object的过程了.我们在这里只看最后的实现,代码如下:
这里的代码一目了然,就是使用我们找到Method,然后进行反射调用.在这里需要注意的一点就是
1.对实例工厂方法注入来说factoryBean不为空,这个反映就是一般我们常用的操作方法
2.对静态工厂来说,factoryBean= null ,这里实现上是invoke(null,args)这个用法我还没用过.不过通过实例证明是没问题的.那么我猜测其实现是判断invoke的第一个参数是不是null,如果是null就在自身的静态方法中找到对应的Method然后处理.因为静态方法不需要实例化.
最后这个实现的代码在SimpleInstantiationStrategy.java里面
在结尾贴上,我对invoke null 示例操作的结果
package com.bruk;
public class Car {
public static void printCar(){
System.out.println("my car");
}
}
Class<?> cls = Car.class;
try {
Method[] methd = cls.getDeclaredMethods();
for (Method mtd : methd) {
System.out.println(mtd.getName());
if (mtd.getName().equals("printCar")) {
mtd.invoke(null,null);
}
}
}catch (Exception e){
System.out.println(e.getMessage());
}
执行打印结果如下