参考 :徒手撸框架--实现IoC
核心技术点:
- 资源解析,如解析定义bean的json文件。 本例用jackson的ObjectMapper解析成List<BeanDefinition>对象。
[
{
"name": "computer",
"className": "com.xiaoyiyiyo.ioc.entity.Computer"
},
{
"name": "cpu",
"className": "com.xiaoyiyiyo.ioc.entity.Cpu"
},
{
"name": "disk",
"className": "com.xiaoyiyiyo.ioc.entity.Disk",
"constructorArgs" : [
{
"index" : 0,
"ref" : "cpu"
},
{
"index" : 1,
"ref" : "disk"
}
]
}
]
- 递归getBean(),利用Java反射生成对象。
效果:
public static void main(String[] args) throws Exception {
JsonApplicationContext applicationContext = new JsonApplicationContext("application.json");
applicationContext.init();
Computer computer = (Computer) applicationContext.getBean("computer");
computer.work();
}
代码(部分):
- 核心基础bean:BeanDefinition,即json资源映射成List<BeanDefinition>.
package com.xiaoyiyiyo.ioc.bean;
import java.util.List;
/**
* Created by xiaoyiyiyo on 2018/3/6.
* 映射bean的定义
*/
public class BeanDefinition {
private String name;
private String className;
private String interfaceName;
private List<ConstructorArg> constructorArgs;
private List<PropertyArg> propertyArgs;
public BeanDefinition() {
}
// get/set方法
...
}
- 解析application.json,生成List<BeanDefinition>, 并注册到相应的Map中, 用于后续判断(比如是否已生成对象等等)
List<BeanDefinition> beanDefinitions = JsonUtils.readValue(is, new TypeReference<List<BeanDefinition>>(){});
if(beanDefinitions != null && !beanDefinitions.isEmpty()) {
for (BeanDefinition beanDefinition : beanDefinitions) {
registerBean(beanDefinition.getName(), beanDefinition);
}
}
- 递归getBean(), 利用Java发射生成对象
public class BeanFactoryImpl implements BeanFactory {
private static final ConcurrentHashMap<String, Object> beanMap =
new ConcurrentHashMap<String, Object>();
private static final ConcurrentHashMap<String, BeanDefinition> beanDefineMap =
new ConcurrentHashMap<String, BeanDefinition>();
private static final Set<String> beanNameSet = Collections.synchronizedSet(new HashSet<String>());
public Object getBean(String name) throws Exception {
// 是否已生成对象
Object bean = beanMap.get(name);
if (bean != null) {
return bean;
}
// 生成bean
bean = createBean(beanDefineMap.get(name));
if (bean != null) {
beanMap.put(name, bean);
}
return bean;
}
public Object createBean(BeanDefinition beanDefinition) throws Exception {
String beanName = beanDefinition.getClassName();
Class clz = ClassUtils.loadClass(beanName);
if (clz == null) {
throw new Exception("can not find bean by beanName: " + beanName);
}
// 此处利用有参构造函数生成并初始化对象了。
// 看资料感觉spring ioc是先用的无参构造函数生成实例,然后再初始化
List<ConstructorArg> constructorArgs = beanDefinition.getConstructorArgs();
List<Class> argClazzs = new ArrayList<Class>();
if (constructorArgs != null && !constructorArgs.isEmpty()) {
List<Object> objects = new ArrayList<Object>();
for (ConstructorArg constructorArg : constructorArgs) {
if (constructorArg != null ) {
if (constructorArg.getValue() != null) {
objects.add(constructorArg.getValue());
} else {
String ref = constructorArg.getRef();
argClazzs.add(ClassUtils.loadClass(beanDefineMap.get(ref).getClassName()));
// 递归
objects.add(getBean(ref));
}
} else {
throw new Exception("An constructor param can't be null.");
}
}
Class[] constructorArgTypes = argClazzs.toArray(new Class[]{});
// Java反射
return BeanUtils.instanceByReflect(clz, constructorArgTypes, objects.toArray());
} else {
return BeanUtils.instanceByReflect(clz, null, null);
}
}
protected void registerBean(String name, BeanDefinition bd){
beanDefineMap.put(name,bd);
beanNameSet.add(name);
}
}
Java反射 BeanUtils
/**
* Created by xiaoyiyiyo on 2018/3/7.
*/
public class BeanUtils {
public static <T> T instanceByCglib(Class<T> clz, Class[] argTypes, Object[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clz);
enhancer.setCallback(NoOp.INSTANCE);
if (ctr == null) {
return (T) enhancer.create();
} else {
return (T) enhancer.create(ctr.getParameterTypes(), args);
}
}
public static <T> T instanceByReflect(Class<T> clz, Class[] argTypes, Object[] args) throws Exception {
if (argTypes == null) {
return (T) clz.newInstance();
}
Constructor constructor = clz.getConstructor(argTypes);
return (T) constructor.newInstance(args);
}
}
初始化对象的代码待续。。。(set方法)
git: https://github.com/xiaoyiyiyo/framework/tree/master/ioc