Spring容器基于控制反转帮助开发者实现了对象的创建过程与调用过程解耦,使得开发更加便捷,并且便于代码维护。而DI则是IOC实现的核心,由于我们将类的实例化交由容器管理,实例与实例之间难免会存在依赖关系,这时依赖注入技术就将发挥其价值。
本章我们使用XML配置文件的方式,实现一个简单的能够实现控制反转和依赖注入的容器。代码较长,并且未经过整理重构,仅作为感兴趣的开发者朋友实现容器功能的简单参考,如果有问题感谢留言指出,博主日后会将代码整理并添加注释。
package runnable;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import annotation.Mark;
import test.packages.son02.User02;
/**
-
简单的容器实现
*/
public class Util {private Element root;
private List<Element> beans;
private static Map<String, Object> beansMap=new HashMap<String, Object>();public static void main(String[] args) throws Exception{
Util util=new Util("utils.xml");User02 u02=util.getBean("user02", User02.class); System.out.println(u02); System.out.println(beansMap); util.destroy();
}
public Util() {
super();
}/*
- @param file_Xml 配置文件的路径及名称
*/
public Util(String file_Xml) {
super();
loadXml(file_Xml);
init();
}
private void loadXml(String file_Xml) {
SAXReader reader=new SAXReader();
Document doc;
try {
doc = reader.read(getClass().getClassLoader().getResource(file_Xml));
root=doc.getRootElement();
beans=root.elements();
} catch (DocumentException e) {
e.printStackTrace();
}
}/*
- 初始化函数,会直接加载xml配置文件
*/
private void init(){
this.createInstanceByXml();
}
/*
- 销毁方法,调用此方法会执行所有在配置文件中注册过的销毁方法
*/
public void destroy(){
for(Element bean:beans) {
String destroy_methodName=bean.attributeValue("destroy-method");
if(destroy_methodName!=null) {
String classId=bean.attributeValue("id");
if(beansMap.containsKey(bean.attributeValue("id"))) {
Class cls;
try {
cls = Class.forName(bean.attributeValue("class"));
Method destroy_method=cls.getMethod(destroy_methodName);
destroy_method.invoke(getBean(classId, cls));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
beansMap.clear();
beansMap=null;
}
/*
- 获取实例的方法
*/
public Object getBean(String classId){
if(beansMap.containsKey(classId)){
return beansMap.get(classId);
}else{
for(Element bean:beans){
if(classId.equals(bean.attributeValue("id"))){
Object obj=createInstanceByRef(classId);
addBeanToMap(bean, obj);
return obj;
}
}
}
return null;
}
/*
- 获取携带类型信息的实例
*/
public <T>T getBean(String classId,Class<T> cls){
return (T)this.getBean(classId);
}
/*
- 通过读取xml文件创建对象
*/
private void createInstanceByXml(){
boolean default_lazy_init=Boolean.parseBoolean(root.attributeValue("default-lazy-init"));
for(Element bean:beans) {
boolean lazy_init;
if(bean.attributeValue("lazy-init")==null) {
lazy_init=default_lazy_init;
}else {
lazy_init=Boolean.parseBoolean(bean.attributeValue("lazy-init"));
}
if(!lazy_init&&!"prototype".equals(bean.attributeValue("scope"))
&&bean.attributeValue("class")!=null) {
createInstance(bean);
}
}
}
/*
- 通过property标签为实例赋值
*/
private void setValueByProperties(Element bean, Object obj) {
List<Element> properties=bean.elements("property");
for(Element property:properties){
String parameterName=property.attributeValue("name");
String setMethodName="set"+parameterName.substring(0,1).toUpperCase()+parameterName.substring(1);
System.out.println(setMethodName);
String parameterValue=property.attributeValue("value");
String parameterRef=property.attributeValue("ref");
Class cls=obj.getClass();
Method[] methods=cls.getDeclaredMethods();
for(Method method:methods){
if(setMethodName.equals(method.getName())){
try {
if(parameterValue!=null){
method.invoke(obj,parameterValue);
}else{
if(beansMap.containsKey(parameterRef)){
method.invoke(obj, beansMap.get(parameterRef));
}else{
Object obj_ref=createInstanceByRef(parameterRef);
addBeanToMap(bean, obj_ref);
method.invoke(obj, obj_ref);
}
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
/*
- 通过引用创建对象
*/
private Object createInstanceByRef(String ref){
for(Element bean:beans) {
if(ref.equals(bean.attributeValue("id"))){
try {
Object obj=null;
if(bean.elements("constructor-arg").size()==0) {
obj=Class.forName(bean.attributeValue("class")).newInstance();
setValueByProperties(bean,obj);
}else {
obj=setValueByConstructor(bean);
setValueByProperties(bean,obj);
}
addBeanToMap(bean, obj);
return obj;
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
return null;
}
/*
- 通过bean对象创建实例
*/
private Object createInstance(Element bean){
try {
Object obj=null;
if(bean.elements("constructor-arg").size()==0) {
obj=Class.forName(bean.attributeValue("class")).newInstance();
setValueByProperties(bean,obj);
}else {
obj=setValueByConstructor(bean);
setValueByProperties(bean,obj);
}
addBeanToMap(bean, obj);
return obj;
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/*
-
通过扫描包的形式创建对象,可以通过createAll参数选择是否创建包下的所有类的实例,此处不同于Spring容器
*/
private void createPackage(String packageName,Boolean createAll){
String packagePath=packageName.replaceAll("\.", "/");
URL packageUrl=this.getClass().getClassLoader().getResource(packagePath);
File pkgFile=new File(packageUrl.getPath());
File[] files_class=pkgFile.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if(file.getName().endsWith(".class")){
return true;
}else if(file.isDirectory()){
try {
createPackage(packageName+"."+file.getName(),createAll);
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
});
for(File file:files_class){
String className=file.getName().substring(0,file.getName().lastIndexOf("."));
Object obj;
if(createAll) {
//创建包下的所有类的实例
try {
obj = Class.forName(packageName+"."+className).newInstance();
String classId=className.substring(0,1).toLowerCase()+className.substring(1);
beansMap.put(classId, obj);
} catch (Exception e) {
e.printStackTrace();
}
}else {
//只创建有Mark注解的类的实例
try {
Class<?> cls=Class.forName(packageName+"."+className);
if(cls.isAnnotationPresent(Mark.class)){
obj=cls.newInstance();
String classId=className.substring(0,1).toLowerCase()+className.substring(1);
beansMap.put(classId,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}}
}
/*
- 不指定是否全部创建时,只创建被标记的
*/
private void createPackage(String packageName) {
this.createPackage(packageName, false);
}
/*
- 使用有参构造器创建对象时调用此方法
*/
private Object setValueByConstructor(Element bean) {
try {
//加载该类
Class<?> cls=Class.forName(bean.attributeValue("class"));
//过的该bean标签下的constructor-atg标签
List<Element> con_args=bean.elements("constructor-arg");
//对constructor-arg标签进行排序,结果保存为Object类型
List<Object> con_arg_values=new ArrayList<>();
for(int i=0;i<con_args.size();i++){
con_arg_values.add(null);
}
for(Element con_arg:con_args) {
String value=con_arg.attributeValue("value");
if(con_arg.attributeValue("index")!=null) {
int index=Integer.parseInt(con_arg.attributeValue("index"));
if(value!=null)
con_arg_values.set(index,value);
else{
String ref=con_arg.attributeValue("ref");
if(beansMap.containsKey(ref)){
con_arg_values.set(index, getBean(ref));
}else{
createInstanceByRef(ref);
con_arg_values.set(index, getBean(ref));
}
}
}else {
for(int i=0;i<con_args.size();i++){
if(con_arg_values.get(i)==null) {
if(value!=null){
con_arg_values.set(i,value);
}else{
String ref=con_arg.attributeValue("ref");
if(beansMap.containsKey(ref)){
con_arg_values.set(i, getBean(ref));
}else{
Object obj=createInstanceByRef(ref);
con_arg_values.set(i, obj);
}
}
break;
}
}
}
}
//获得该类的所有构造器
Constructor<?>[] cons=cls.getDeclaredConstructors();
for(Constructor<?> con:cons) {
//按照constructor-arg标签的顺序,尝试执行每一个形参个数相同的构造器
if(con.getParameterCount()==con_args.size()) {
List<Object> parametersList=new ArrayList<>();
Class<?>[] parameterTypes=con.getParameterTypes();
for(int i=0;i<parameterTypes.length;i++) {
addToParametersList(con_arg_values.get(i),parameterTypes[i],parametersList);
}
try {
return con.newInstance(parametersList.toArray());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/*
- 完成类型转换并将参数的值加入实参列表
*/
private void addToParametersList(Object obj,Class cls,List<Object> parametersList){
String parameterType=cls.getName();
String value=String.valueOf(obj);
if("java.lang.String".equals(parameterType)) {
parametersList.add(value);
}else if("int".equals(parameterType)) {
parametersList.add(Integer.parseInt(value));
}else if("short".equals(parameterType)) {
parametersList.add(Short.parseShort(value));
}else if("long".equals(parameterType)) {
parametersList.add(Long.parseLong(value));
}else if("double".equals(parameterType)) {
parametersList.add(Double.parseDouble(value));
}else if("float".equals(parameterType)) {
parametersList.add(Float.parseFloat(value));
}else if("char".equals(parameterType)&&value.length()==1) {
parametersList.add(value.charAt(0));
}else if("boolean".equals(parameterType)) {
parametersList.add(Boolean.parseBoolean(value));
}else{
parametersList.add(obj);
}
}
/*
- 尝试将新创建的实例加入Map中(这里我们只考虑单例与多例两种作用域)
*/
private void addBeanToMap(Element bean,Object obj){
if(!"prototype".equals(bean.attributeValue("scope"))){
beansMap.put(bean.attributeValue("id"), obj);
}
}
- @param file_Xml 配置文件的路径及名称
}