程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> spring如何實現注入,spring實現注入

spring如何實現注入,spring實現注入

編輯:JAVA綜合教程

spring如何實現注入,spring實現注入


spring如何實現注入

IOC(Inverse of Control)可翻譯為“控制反轉”,但大多數人都習慣將它稱為“依賴注入”。在Spring中,通過IOC可以將實現類 、參數信息等配置在其對應的配置文件中 ,那麼當需要更改實現類或參數信息時,只需要修改配置文件即可,這種方法在上例的基礎上更進一步的降低了類與類之間的耦合。我們還可以對某對象所需要的其它對象進行注入 ,這種注入都是在配置文件中做的,Spring的IOC的實現原理利用的就是Java的反射機制,Spring還充當了工廠的角色,我們不需要自己建立工廠類 。Spring的工廠類會幫我們完成配置文件的讀取、利用反射機制注入對象等工作,我們可以通過bean的名稱獲取對應的對象。

定義一個bean src/main/java/spring_IOC/JavaBean.java

package spring_IOC;

/**
 * Created by tom on 2016/5/18.
 */
public class JavaBean {
    String username;
    String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

實例化一個類,利用反射,將其注入值 src/main/java/spring_IOC/SetValueByReflection.java

package spring_IOC;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by tom on 2016/5/18.
 */
public class SetValueByReflection {
    /**
     * 實例化一個類,利用反射,將其注入值
     */
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        JavaBean bean = new JavaBean();
        //獲取指定類的指定方法,
        Class c = Class.forName("spring_IOC.JavaBean");
        Method method = c.getMethod("setUsername", new Class[]{String.class});
        //對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法,調用對象javaBean的setuserName方法,參數為"hello world"
        method.invoke(bean, "hello world");
        System.out.println(bean.getUsername());
    }
}

實例化一個類,利用反射,用個map來摸擬在xml獲取的屬性名及值 src/main/java/spring_IOC/SetValueByReflectionLoop.java

package spring_IOC;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by tom on 2016/5/18.
 */
public class SetValueByReflectionLoop {
    static Logger log = LoggerFactory.getLogger(BeanFactory.class);

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, IntrospectionException {
        //這個map對象用來模擬對屬性文件解析獲了的屬性名與值
        Map<String, Object> map = new HashMap<>();
        map.put("username", "tomLuo");
        map.put("password", "954");

        Class bean = Class.forName("spring_IOC.JavaBean");
        Object obj = bean.newInstance();
        //獲取對應class信息
        BeanInfo info = Introspector.getBeanInfo(bean);
        // 遍歷指定類的屬性
        PropertyDescriptor[] propertys = info.getPropertyDescriptors();
        for (int j = 0; j < propertys.length; j++) {
            System.out.println("屬性:" + propertys[j].getName());
        }
        //獲取其屬性描述
        java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
        Method mSet = null;
        for (int k = 0; k < pd.length; k++) {
            if (map.containsKey(pd[k].getName())) {
                Object value=map.get(pd[k].getName());//將對應的屬性值取出來
                mSet = pd[k].getWriteMethod();
                log.info("{} {} {}", pd[k].getName(), pd[k].getWriteMethod().getName(), pd[k].getReadMethod().getName());//password setPassword getPassword
                mSet.invoke(obj, value);//利用反射將567注入到bean 這兒實驗將每個set方法的值都設置為567
            }
        }
        //將對象放入beanMap中,其中key為id值,value為對象
        JavaBean javaBean1 = (JavaBean) obj;
        System.out.println("userName=" + javaBean1.getUsername());
        System.out.println("password=" + javaBean1.getPassword());

    }
}

加載xml文件,利用反射,將其注入值 src/main/resources/config.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans">
    <bean id="javaBean" class="spring_IOC.JavaBean">
        <property name="username" value="tom"/>

        <property name="password" value="123"/>

    </bean>
</beans>

Bean工廠主要用來解析xml文件,獲取屬性名及值,然後利用反射,將其注入值 src/main/java/spring_IOC/BeanFactory.java

package spring_IOC;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by tom on 2016/5/18.
 */
public class BeanFactory {

    static Logger log = LoggerFactory.getLogger(BeanFactory.class);
    private Map<String, Object> beanMap = new HashMap<String, Object>();

    /**
     * bean工廠的初始化
     *
     * @param xml
     */
    public void init(String xml) {
        try {
            //讀取指定的配置文件
            SAXReader reader = new SAXReader();
            //從class目錄下獲取指定的配置文件
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = classLoader.getResourceAsStream(xml);

            //讀取xml文件
            Document document = reader.read(inputStream);
            //獲取跟節點
            Element root = document.getRootElement();
            //遍歷bean節點
            Element foo;
            for (Iterator iteBean = root.elementIterator("bean"); iteBean.hasNext(); ) {
                foo = (Element) iteBean.next();
                //獲取bean的屬性id和class
                Attribute id = foo.attribute("id");
                Attribute cls = foo.attribute("class");
                //利用java反射機制,通過class的名稱獲取Class對象
                log.debug("{}", cls.getText());
                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;
                //創建一個對象(創建此 Class 對象所表示的類的一個新實例。如同用一個帶有一個空參數列表的 new 表達式實例化該類。如果該類尚未初始化,則初始化這個類。)
                Object obj = bean.newInstance();

                //遍歷該bean的property屬性
                for (Iterator iteProperty = foo.elementIterator("property"); iteProperty.hasNext(); ) {
                    Element elementProperty = (Element) iteProperty.next();
                    //獲取該property的name屬性
                    Attribute name = elementProperty.attribute("name");
                    //讀取該屬性值
                    String value = elementProperty.attribute("value").getText();
                    //String value = null;
                    //獲取該property的子元素value的值
                    //for(Iterator iteValue = elementProperty.elementIterator("value");iteValue.hasNext();){
                    //      Element elementValue = (Element)iteValue.next();
                    //      value = elementValue.getText();
                    //      break;
                    //}
                    for (int k = 0; k < pd.length; k++) {
                        log.info(pd[k].getName());
                        if (pd[k].getName().equalsIgnoreCase(name.getText())) {
                            mSet = pd[k].getWriteMethod();//
                            log.info(mSet.getName());
                            //利用Java的反射機制調用對象的某個set方法,並將值設置進去
                            mSet.invoke(obj, value);//通過invoke方法來調用特定對象的特定方法,實現的原理都是基於Java的反射機制
                        }
                    }
                }
                //將對象放入beanMap中,其中key為id值,value為對象
                beanMap.put(id.getText(), obj);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 通過bean的id獲取bean的對象.
     *
     * @param beanName bean的id
     * @return 返回對應對象
     */
    public Object getBean(String beanName) {
        Object obj = beanMap.get(beanName);
        return obj;
    }

    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());
    }
}

可以看到,雖然在main()方法中沒有對屬性賦值,但屬性值已經被注入,在BeanFactory類中的Class bean = Class.forName(cls.getText()); 通過類名來獲取對應的類,mSet.invoke(obj, value);通過invoke方法來調用特定對象的特定方法,實現的原理都是基於Java的反射機制          

 

源碼浏覽: https://github.com/tomlxq/job-test/tree/master/java-base/src/main/java/spring_IOC 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved