Java反射机制的应用-模拟Spring的依赖注入

来源:互联网 发布:电脑gif制作软件 编辑:程序博客网 时间:2024/05/21 13:21

Java反射机制应用非常广泛,在很多框架中都得到应用,也是学习动态代理和Java开源框架的基础,下面采用Java的反射机制,结合XML文档解析,模拟Spring中的setter方法依赖注入。

一、整体架构图

        

二、具体代码实现

   1、Student.java

            package cn.com.bochy.entity;
import java.io.Serializable;
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
  public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
  public Student() {
// TODO Auto-generated constructor stub
}
}

2、Teacher.java

   package cn.com.bochy.entity;
public class Teacher {
   public Student s1;
public void setS1(Student s1) {
this.s1 = s1;
}
public void putS1(int id,String name){
s1.setId(id);
s1.setName(name);
}
  public void show(){
 System.out.println(s1.getId()+"  "+s1.getName());
  }
}

3、Bean,java

   package cn.com.bochy.xml.entity;
/**
 * @author 陈征峰 
 * 定义一个类,用来存储读取配置文件的一个bean的信息 成员变量和配置文件中的bean的属性一样
 */
public class Bean {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
   public String getClassName() {
return className;
}


public void setClassName(String className) {
this.className = className;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
/**
* bean的id属性
*/
private String id;
// bean的class属性
private String className;
// bean的name属性
private String name;
// bean的ref属性
private String ref;
// bean的value属性
private String value;
}

4、ParseXML.java

package cn.com.bochy.xml;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.VisitorSupport;
import org.dom4j.io.SAXReader;
import cn.com.bochy.xml.entity.Bean;
/**
 * @author 陈征峰 
 * 使用观察者模式,解析XML文档,并把解析后的信息存入列表listBeans中
 */
public class ParseXML extends VisitorSupport {
public static List<Bean> listBeans = new ArrayList<Bean>();
String beanName="";
Bean bean = null;
String id=null;
public void visit(Element element) {
if (element.getName().equals("bean")) {
  bean=new Bean();
  listBeans.add(bean);
}
}
public void visit(Attribute attr) {
  if(attr.getName().equals("name")){
  bean.setName(attr.getText());
  
  }
  if(attr.getName().equals("ref")){
  bean.setRef(attr.getText());
  
  }
  if(attr.getName().equals("class")){
  bean.setClassName(attr.getText());
  
  }
  if(attr.getName().equals("id")){
  bean.setId(attr.getText());
  
  }

}
/**
* 读取XML文档
*/
public static void readXML(){
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(new File("src/applicationContext.xml"));
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Element root = document.getRootElement();
ParseXML p = new ParseXML();
root.accept(p);
}
//首字母变为大写
public static  String FristBig(String name){
return name.substring(0,1).toUpperCase()+name.substring(1);
}
}
5、ApplicationContext.java
package cn.com.bochy.spring;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import cn.com.bochy.xml.ParseXML;
import cn.com.bochy.xml.entity.Bean;
/**
 * 
 * @author 陈征峰 
 * 创建类似Spring容器的类ApplicationContext,调用getBean方法,获取对象
 * 
 */
public class ApplicationContext {
/**
* 所有创建好的对象都存入beans中,其中key对应配置文件中的id属性,value是存入的bean的对象
*/
private static Map<String, Object> beans = new HashMap<String, Object>();
// 根据id属性获取对应的bean对象
public static Object getBean(String beanid) {
DI();
Object obj = null;
for (String id : beans.keySet()) {
if (id.equals(beanid)) {
obj = beans.get(id);
// System.out.println(obj.getClass().getName());
}
}
return obj;
}
/**
* 采用Java的反射机制,根据配置文件,
* 把一个B对象依赖注入另一个A对象中
*/
public static void DI() {
//解析XML文档
ParseXML.readXML();
//遍历ParseXML.listBeans,查找哪些bean需要依赖注入
for (Bean bName : ParseXML.listBeans) {
//如果bName需要依赖注入
if (bName.getName() != null) {
//获取需要注入bean的id
String ref = bName.getRef();
 //查找需要注入bean
for (Bean bref : ParseXML.listBeans) {
 //找到
if (bref.getId().equals(ref)) {
try {
//采用Java的反射机制,生成一个注入bean的类对象
Class<?> c1 = Class.forName(bref.getClassName());
//采用Java的反射机制,生成一个注入bean的对象,也就是B对象
Object c1Object = c1.newInstance();
//采用Java的反射机制,生成一个被注入bean的类对象
Class<?> bean = Class.forName(bName.getClassName());
//采用Java的反射机制,找到对应的setter方法
Method m = bean.getDeclaredMethod("set" + ParseXML.FristBig(bName.getName()),c1);
                //采用Java的反射机制,生成一个被注入bean的对象,也就是A对象
Object obj = bean.newInstance();
     //采用Java的反射机制,调用setter方法,把c1Object对象注入obj对象中
m.invoke(obj, c1Object);
//把obj对象存入beans中。
beans.put(bName.getId(), obj);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
}
}
}
}
}

6、配置文件 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="s" class="cn.com.bochy.entity.Student"></bean>
<bean id="teacher" class="cn.com.bochy.entity.Teacher">
<property name="s1" ref="s"></property>
</bean>
</beans>

7、Test,java

  package cn.com.bochy.test;
import cn.com.bochy.entity.Teacher;
import cn.com.bochy.spring.ApplicationContext;
public class Test {
public static void main(String[] args) {
 ApplicationContext context=new ApplicationContext();
  Teacher t1=(Teacher)context.getBean("teacher");
  t1.putS1(12, "sdwe2");
  t1.show();
}
}


原创粉丝点击