Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”。在Spring中,通过IOC可以将实现类、参数信息等配置在其对应的配置文件中,那么当 需要更改实现类或参数信息时,只需要修改配置文件即可,这种方法在上例的基础上更进一步的降低了类与类之间的耦合。我们还可以对某对象所需要的其它对象进 行注入,这种注入都是在配置文件中做的,Spring的IOC的实现原理利用的就是Java的反射机制, Spring还充当了工厂的角色,我们不需要自己建立工厂类。Spring的工厂类会帮我们完成配置文件的读取、利用反射机制注入对象等工作,我们可以通 过bean的名称获取对应的对象。

下面让我们看看如下的模拟Spring的bean工厂类:

 package org.amigo.reflection;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* bean工厂类.
*/
public class BeanFactory {
       private Map<String, Object> beanMap = new HashMap<String, Object>();
       /**
       * bean工厂的初始化.
       * @param xml xml配置文件
       */
       public void init(String xml) {
              try {
                     //读取指定的配置文件
                     SAXReader reader = new SAXReader();
                     ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                     //从class目录下获取指定的xml文件
                     InputStream ins = classLoader.getResourceAsStream(xml);
                     Document doc = reader.read(ins);
                     Element root = doc.getRootElement();
                     Element foo;

                     //遍历bean
                     for (Iterator i = root.elementIterator("bean"); i.hasNext();) {
                            foo = (Element) i.next();
                            //获取bean的属性id和class
                            Attribute id = foo.attribute("id");
                            Attribute cls = foo.attribute("class");

                            //利用Java反射机制,通过class的名称获取Class对象
                            Class bean = Class.forName(cls.getText());

                            //获取对应class的信息
                            java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
                            //获取其属性描述
                            java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
                            //设置值的方法
                            Method mSet = null;
                            //创建一个对象
                            Object obj = bean.newInstance();

                            //遍历该bean的property属性
                            for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {
                                   Element foo2 = (Element) ite.next();
                                   //获取该property的name属性
                                   Attribute name = foo2.attribute("name");
                                   String value = null;

                                   //获取该property的子元素value的值
                                   for(Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
                                          Element node = (Element) ite1.next();
                                          value = node.getText();
                                          break;
                                   }

                                   for (int k = 0; k < pd.length; k++) {
                                          if (pd[k].getName().equalsIgnoreCase(name.getText())) {
                                                 mSet = pd[k].getWriteMethod();
                                                 //利用Java的反射极致调用对象的某个set方法,并将值设置进去
                                                 mSet.invoke(obj, value);
                                          }
                                   }
                            }

                            //将对象放入beanMap中,其中key为id值,value为对象
                            beanMap.put(id.getText(), obj);
                     }
              } catch (Exception e) {
                     System.out.println(e.toString());
              }
       }

       /**
       * 通过bean的id获取bean的对象.
       * @param beanName bean的id
       * @return 返回对应对象
       */
       public Object getBean(String beanName) {
              Object obj = beanMap.get(beanName);
              return obj;
       }

       /**
       * 测试方法.
       * @param args
       */
       public static void main(String[] args) {
              BeanFactory factory = new BeanFactory();
              factory.init("config.xml");
              JavaBean javaBean = (JavaBean) factory.getBean("javaBean");
              System.out.println("userName=" + javaBean.getUserName());
              System.out.println("password=" + javaBean.getPassword());
       }
}

该类的init(xml)方法,通过指定的xml来给对象注入属性,为了对该类进行测试,我还需要新建一个JavaBean和在src目录下新建一个名为config.xml的配置文件。JavaBean的内容如下:

 package org.amigo.reflection;
/**
*
* 简单的bean,用于测试
*/
public class JavaBean {
       private String userName;
       private String password;

    public String getPassword() {
              return password;
       }
       public String getUserName() {
              return userName;
       }
       public void setUserName(String userName) {
              this.userName = userName;
       }
       public void setPassword(String password) {
              this.password = password;
       }
}

这个简单bean对象中有两个属性,分别为userName和password,下面我们在配置文件config.xml中对其属性注入对应的属性值。配置文件内容如下:

 <?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="javaBean" class="org.amigo.reflection.JavaBean">
       <property name="userName">
           <value>阿蜜果</value>
       </property>
       <property name="password">
           <value>12345678</value>
       </property>
    </bean>
</beans>

类与配置文件都完成后,可以运行BeanFactory.java文件,控制台显示内容为:

userName=阿蜜果

password=12345678

可以看到,虽然在main()方法中没有对属性赋值,但属性值已经被注入,在 BeanFactory类中的Class bean = Class.forName(cls.getText());通过类名来获取对应的类,mSet.invoke(obj, value);通过invoke方法来调用特定对象的特定方法,实现的原理都是基于Java的反射机制,在此我们有一次见证了Java反射机制的强大。

当然,这只是对IOC的一个简单演示,在Spring中,情况要复杂得多,例如,可以一个bean引用另一个bean,还可以有多个配置文件、通过多种方式载入配置文件等等。不过原理还是采用Java的反射机制来实现IOC的。

四.

在本文中,笔者通过讲述Java反射机制概述与初探、IOC使用的背景、IOC粉墨登场等内容,演示了Java反射机制API的强大功能,并通过编写自己的简单的IOC框架,让读者更好的理解了IOC的实现原理。

本文通过IOC的一个简要实现实例,模拟了Spring中IOC的实现,虽然只是完成了
Spring中依赖注入的一小部分工作,但是很好的展现了Java反射机制在Spring中的应用,能使我们能更好的从原理上了解IOC的实现,也能为我
们实现自己的准Spring框架提供

时间: 2024-10-29 19:11:51

Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring的相关文章

Java反射机制详解

Java反射机制详解 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制. 1.关于Class 1.Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性    2.对象照镜子后(反射)可以得到的信息:某个类的数据成员名.方法和构造器.某个类到底实现

Java 反射机制详解(下)

续:Java 反射机制详解(上) 三.怎么使用反射 想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象. 获取字节码文件对象的三种方式.  1.Class class1= Class.forName("全限定类名"); //通过Class类中的静态方法forName,

java异常处理机制详解

java异常处理机制详解 程序很难做到完美,不免有各种各样的异常.比如程序本身有bug,比如程序打印时打印机没有纸了,比如内存不足.为了解决这些异常,我们需要知道异常发生的原因.对于一些常见的异常,我们还可以提供一定的应对预案.C语言中的异常处理是简单的通过函数返回值来实现的,但返回值代表的含义往往是由惯例决定的.程序员需要查询大量的资料,才可能找到一个模糊的原因.面向对象语言,比如C++, Java, Python往往有更加复杂的异常处理机制.这里讨论Java中的异常处理机制. 异常处理 Ja

[转]Java反射机制详解

目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为Integer的ArrayList中存放一个String类型的对象. ·通过反射取得并修改数

Java中反射机制详解

序言 在学习java基础时,由于学的不扎实,讲的实用性不强,就觉得没用,很多重要的知识就那样一笔带过了,像这个马上要讲的反射机制一样,当时学的时候就忽略了,到后来学习的知识中,很多东西动不动就用反射,所以回过头来把这个给重新补一下,自己欠下的债,迟早是要还的. ---WH 一.什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的

java 动态性之反射机制 详解 案例

1.反射机制 2.动态编译 3.动态执行javassript代码 4.动态字节码操作 动态语言 程序运行时,可以改变程序结构或变量类型.典型的语言: 1):Python.ruby.javascript等. 2):如下javascript代码: funtion test(){ var s ="var a=3;var b=5;alert(a+b);"; eval(s); } 3):C,C++,JAVA不是动态语言,JAVA可以称之为"准动态语言".但是JAVA有一定的动

【转载】Java反射机制详解

转自:http://baike.xsoftlab.net/view/209.html#3_8 1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2反射机制能做什么 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类: 在运行时构造任意一个类的对象: 在运行时判断任意一个类所具有的成员变量和方法: 在运行时调用任意一个

java反射机制详解 及 Method.invoke解释 getMethod

JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理.1. 得到某个对象的属性 public Object getProperty(Obje

java反射机制详解 及 Method.invoke解释

JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理.1. 得到某个对象的属性 Java代码   public Object getProp