public class BeanDefinition {
private String className;//class
private String beanName; //id
private String initMethod; //init_method
//该配置是默认配置,单例
private String scope;
private static final String SCOPE_SINGLETON = "singleton";
private static final String SCOPE_PROTOTYPE = "prototype";
/**
* bean中的属性信息
*/
private List propertyValues = new ArrayList();
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public BeanDefinition(String className, String beanName) {
this.className = className;
this.beanName = beanName;
}
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public String getInitMethod() {
return initMethod;
}
public void setInitMethod(String initMethod) {
this.initMethod = initMethod;
}
public List getPropertyValues() {
return propertyValues;
}
public void addPropertyValue(PropertyValue propertyValue) {
this.propertyValues.add(propertyValue);
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public void setPropertyValues(List propertyValues) {
this.propertyValues = propertyValues;
}
public boolean isSingleton() {
return SCOPE_SINGLETON.equals(this.scope);
}
public boolean isPrototype() {
return SCOPE_PROTOTYPE.equals(this.scope);
}
@Override
public String toString() {
return "BeanDefinition{" +
"className='" + className + '\'' +
", beanName='" + beanName + '\'' +
", initMethod='" + initMethod + '\'' +
", scope='" + scope + '\'' +
", propertyValues=" + propertyValues +
'}';
}
}
public class PropertyValue {
private String name;
private Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
@Override
public String toString() {
return "PropertyValue{" +
"name='" + name + '\'' +
", value=" + value +
'}';
}
}
public class RuntimeBeanReference {
private String ref;
public RuntimeBeanReference(String ref) {
this.ref = ref;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
}
public class TypedStringValue {
private String value;
private Class> targetType;
public TypedStringValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Class> getTargetType() {
return targetType;
}
public void setTargetType(Class> targetType) {
this.targetType = targetType;
}
}
public class IocDemo {
//单例bean存放map集合
private static Map singletonObjects=new HashMap();
//封装xml中的bean标签表示的信息
private Map beanDefinitionMap=new HashMap();
@Before
public void demo(){
loadAndRegisterBeanDefinitions("beans.xml");
Set> entries = beanDefinitionMap.entrySet();
for (Map.Entry entry : entries) {
System.out.println(entry.getKey()+"="+entry.getValue());
}
}
@Test
public void iocTest(){
// StudentService studentService = (StudentService)getBean("studentService");
// List all = studentService.findAll();
// for (Student student : all) {
// System.out.println("student = " + student);
// }
UserService userService=(UserService)getBean("userService");
userService.say();
//UserDao userDao=(UserDao)getBean("userDao");
//userDao.say();
// BasicDataSource basicDataSource=(BasicDataSource)getBean("dataSource");
// System.out.println(basicDataSource.getDriverClassName());
// System.out.println(basicDataSource.getUrl());
// System.out.println(basicDataSource.getUsername());
// System.out.println(basicDataSource.getPassword());
}
private Object getBean(String beanName) {
System.out.println("beanName = " + beanName);
Object singletonObject= singletonObjects.get(beanName);
if (singletonObject != null) {
return singletonObject;
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
return null;
}
List propertyValues = beanDefinition.getPropertyValues();
System.out.println("propertyValues = " + propertyValues);
//判断是否是单例还是多例
if (beanDefinition.isSingleton()){
//单例
singletonObject=createBean(beanDefinition);
this.singletonObjects.put(beanName, singletonObject);
}else if (beanDefinition.isPrototype()){
//多例
singletonObject=createBean(beanDefinition);
}
return singletonObject;
}
private Object createBean(BeanDefinition beanDefinition) {
String className = beanDefinition.getClassName();
Class> clazz = resolveClass(className);
if (clazz == null) {
return null;
}
//实例化 new
Object bean=createBeanInstance(clazz);
// 属性填充 set
populateBean(bean, beanDefinition);
// 初始化 init
initBean(bean, beanDefinition);
return bean;
}
//实例化
private Object createBeanInstance(Class> clazz) {
// TODO 可以根据bean标签的配置选择使用实例工厂去创建Bean
// TODO 可以根据bean标签的配置选择使用静态工厂去创建Bean
// 还可以选择使用我们的构造方法去创建Bean
return createObject(clazz);
}
private Object createObject(Class> clazz, Object... args) {
try {
System.out.println("args = " + args);
// TODO 可以根据输入参数获取指定构造参数的构造方法
Constructor> constructor = clazz.getDeclaredConstructor();
// 默认调用无参构造进行对象的创建
return constructor.newInstance(args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//实例化
// private Object createInstance(BeanDefinition beanDefinition) {
// try {
// String clazzName = beanDefinition.getClassName();
// Class> clazzType = resolveClass(clazzName);
// Constructor> constructor = clazzType.getConstructor();
// Object bean = constructor.newInstance();
// return bean;
// } catch (Exception e) {
// e.printStackTrace();
// }
// return null;
// }
private Class> resolveClass(String className) {
try {
Class> clazz = Class.forName(className);
return clazz;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
//属性填充
private void populateBean(Object bean, BeanDefinition beanDefinition) {
List propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
Object valueToUse = null;
if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
String stringValue = typedStringValue.getValue();
Class> targetType = typedStringValue.getTargetType();
if (targetType == String.class) {
valueToUse = stringValue;
} else if (targetType == Integer.class) {
valueToUse = Integer.parseInt(stringValue);
} // ....
} else if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference reference = (RuntimeBeanReference) value;
String ref = reference.getRef();
// 创建一个bean的时候,根据依赖注入情况,自动去创建另一个bean去注入
valueToUse = getBean(ref);
}
setProperty(bean, name, valueToUse);
}
}
private void setProperty(Object bean, String name, Object valueToUse) {
try {
Class> clazz = bean.getClass();
System.out.println("clazz = " + clazz);
//返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
//name 参数是一个 String,它指定所需字段的简称
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(bean, valueToUse);
} catch (Exception e) {
e.printStackTrace();
}
}
//初始化
private void initBean(Object bean, BeanDefinition beanDefinition) {
// TODO Aware接口会在此时被处理
invokeInitMethod(bean, beanDefinition);
}
private void invokeInitMethod(Object bean, BeanDefinition beanDefinition) {
// bean标签配置了init-method属性
String initMethod = beanDefinition.getInitMethod();
if (initMethod == null || initMethod.equals("")) {
return;
}
invokeMethod(bean, initMethod);
// TODO bean标签实现了InitializingBean接口
}
private void invokeMethod(Object bean, String initMethod) {
try {
Class> clazz = bean.getClass();
Method method = clazz.getDeclaredMethod(initMethod);
method.invoke(bean);
} catch (Exception e) {
e.printStackTrace();
}
}
private void loadAndRegisterBeanDefinitions(String location) {
//加载流对象
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location);
//通过sax解析
Document document = DocumentUtils.createDocument(resourceAsStream);
//解析beans文件
parseXMLBeans(document.getRootElement());
}
//解析beans文件
private void parseXMLBeans(Element rootElement) {
List elements = rootElement.elements();
for (Element beanElement : elements) {
//获取标签的名称
String name = beanElement.getName();
if (name.equals("bean")){
//解析
parseXMLBean(beanElement);
}else {
//解析自定义标签
parseXMLCustom(beanElement);
}
}
}
//解析自定义标签
private void parseXMLCustom(Element beanElement) {
}
//解析
private void parseXMLBean(Element beanElement) {
if (beanElement == null) {
return;
}
String id = beanElement.attributeValue("id");
String clazz = beanElement.attributeValue("class");
String initMethod = beanElement.attributeValue("init-method");
String scope = beanElement.attributeValue("scope");
if (scope==null) scope="singleton";
//将数据封装到
BeanDefinition beanDefinition=new BeanDefinition(clazz, id);
beanDefinition.setInitMethod(initMethod);
beanDefinition.setScope(scope);
//解析bean的子标签
List propertyElements = beanElement.elements();
for (Element propertyElement : propertyElements) {
parseXMLProperties(beanDefinition,propertyElement);
}
//注册beanDefinition信息
this.beanDefinitionMap.put(id, beanDefinition);
}
//解析properties文件
private void parseXMLProperties(BeanDefinition beanDefinition, Element propertyElement) {
if (propertyElement == null) {
return;
}
//获取name属性
String name = propertyElement.attributeValue("name");
String value = propertyElement.attributeValue("value");
String ref = propertyElement.attributeValue("ref");
// 如果value和ref都有值,则返回
if (value != null && !value.equals("") && ref != null && !ref.equals("")) {
return;
}
PropertyValue propertyValue=null;
if (value!=null && !value.equals("")){
// 因为spring配置文件中的value是String类型,而对象中的属性值是各种各样的,所以需要存储类型
TypedStringValue typeStringValue = new TypedStringValue(value);
Class> targetType = getTypeByFieldName(beanDefinition.getClassName(),name);
typeStringValue.setTargetType(targetType);
propertyValue = new PropertyValue(name, typeStringValue);
beanDefinition.addPropertyValue(propertyValue);
}else if (ref!=null && !ref.equals("")){
RuntimeBeanReference reference=new RuntimeBeanReference(ref);
propertyValue=new PropertyValue(name, reference);
beanDefinition.addPropertyValue(propertyValue);
}else {
return;
}
}
private Class> getTypeByFieldName(String beanClassName, String name) {
try {
Class> clazz = Class.forName(beanClassName);
Field field = clazz.getDeclaredField(name);
return field.getType();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}