準(zhǔn)備工作做完之后我們就開始依賴注入之旅了:
好了,廢話不多說了,下面即將進(jìn)入我們的正題,依賴注入的三種方式(setter注入、構(gòu)造注入、接口注入):
先建立三種方式都會(huì)用到的類和接口
接口:Arrow(箭)、Person(人)
實(shí)現(xiàn)類:ArrowImpl、PersonImpl
測(cè)試類:MainTest
Arrow接口:
package iocdi;public interface Arrow { public String getArrow();}
Person接口:
package iocdi;public interface Person { public void hunt();}
ArrowImpl類:
package iocdi;public class ArrowImpl implements Arrow { @Override public String getArrow() { return "an arrow"; }}
PersonImpl類:
package iocdi;public class PersonImpl implements Person { private Arrow arrow; @Override public void hunt() { System.out.println("I get " + arrow.getArrow() + " to hunt."); } //set注入一支箭 public void setArrow(Arrow arrow) { this.arrow = arrow; }}
MainTest類:
package iocdi;import org.springframework.context.applicationContext;import org.springframework.context.support.ClassPathxmlApplicationContext;/** * @author ForeverLover */public class MainTest { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml"); System.out.println("-----------------setter注入-----------------"); Person p = ac.getBean("PersonImpl",PersonImpl.class); p.hunt(); }}
看到測(cè)試類會(huì)有疑問,ApplicationContext.xml從哪兒冒出來的,這里要說的就是Spring容器幫助我們?nèi)?chuàng)建實(shí)例對(duì)象bean,在進(jìn)程啟動(dòng)時(shí),Spring容器會(huì)自動(dòng)加載此配置文件,解析通過配置文件配置的bean并創(chuàng)建對(duì)應(yīng)類的實(shí)例,被調(diào)用者使用指定方式注入到調(diào)用者中,從而控制反轉(zhuǎn)和依賴注入。ApplicationContext.xml配置文件內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="ArrowImpl" class="iocdi.ArrowImpl"/> <bean id="PersonImpl" class="iocdi.PersonImpl"> <!-- setter注入 --> <property name="arrow" ref="ArrowImpl"/> </bean> </beans>
所有工作都完成了,然后從測(cè)試類MainTest的main方法執(zhí)行一下,從控制臺(tái)可以看到結(jié)果,是OK的:
setter注入講完了,現(xiàn)在我們來聊聊構(gòu)造注入了,所謂構(gòu)造注入就是在實(shí)例化對(duì)象的時(shí)候就把參數(shù)傳給這個(gè)對(duì)象,我們知道對(duì)于JavaBean都必須有構(gòu)造器,最少有一個(gè)無參構(gòu)造器,到這我們可以繼續(xù)下面的構(gòu)造注入,與setter注入不同之處在于,PersonImpl獲得ArrowImpl實(shí)例的方法,接口Arrow和Person不變,ArrowImpl類也不變,我們修改一下PersonImpl類和ApplicationContext.xml文件:
修改后的PersonImpl類:
package iocdi;public class PersonImpl implements Person { private Arrow arrow; public PersonImpl() {} public PersonImpl(Arrow arrow) { this.arrow = arrow; } @Override public void hunt() { System.out.println("I get " + arrow.getArrow() + " to hunt."); } }
修改后的ApplicationContext.xml文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="ArrowImpl" class="iocdi.ArrowImpl"/> <bean id="PersonImpl" class="iocdi.PersonImpl"> <!-- 構(gòu)造注入 --> <constructor-arg ref="ArrowImpl"/> </bean> </beans>
然后再次運(yùn)行一下MainTest測(cè)試類,看結(jié)果,仍然可行:
不同于setter注入和構(gòu)造注入,接口注入無需在xml文件里配置bean,而利用Java反射創(chuàng)建實(shí)現(xiàn)接口類的實(shí)例。
讓我們來修改一下MainTest測(cè)試類和PersonImpl類:
修改的PersonImpl類:
package iocdi;public class PersonImpl implements Person { private Arrow arrow; @Override public void hunt() { try { Object obj = Class.forName("iocdi.ArrowImpl").newInstance(); arrow = (Arrow) obj; System.out.println("I get " + arrow.getArrow() + " to hunt."); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalaccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
修改的MainTest類:
package iocdi;/** * @author ForeverLover */public class MainTest { public static void main(String[] args) { try { Object obj = Class.forName("iocdi.PersonImpl").newInstance(); Person p = (Person) obj; System.out.println("-----------------接口注入-----------------"); p.hunt(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
運(yùn)行一下測(cè)試類,從控制臺(tái)得出結(jié)果:
說到這順便說一下Lookup方法注入吧,對(duì)于Lookup注入需要一下幾個(gè)類:
Arrow類
Person抽象類
MainTest測(cè)試類
創(chuàng)建Arrow類:
package iocdi;import java.util.Random;public class Arrow { private String arrow; private String[] arrows = {"aaaaArrow", "bbbbArrow", "ccccArrow","ddddArrow","eeeeArrow", "ffffArrow","ggggArrow","hhhhArrow","iiiiArrow"}; public Arrow() { this.arrow = arrows[new Random().nextInt(9)]; } public void getArrow() { System.out.println("I get a " + arrow); } }
創(chuàng)建Person類:
package iocdi;public abstract class Person { public abstract Arrow createArrow(); public Arrow getArrow() { return new Arrow(); } }
創(chuàng)建MainTest類:
package iocdi;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author ForeverLover */public class MainTest { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Person p = ac.getBean("Person", Person.class); Arrow arrow1 = p.getArrow(); Arrow arrow2 = p.getArrow(); System.out.println(arrow1.equals(arrow2)); System.out.println("------------I am a dividing line------------"); Arrow arrow3 = p.createArrow(); Arrow arrow4 = p.createArrow(); System.out.println(arrow3.equals(arrow4)); }}
修改ApplicationContext.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="Arrow" class="iocdi.Arrow"/> <bean id="Person" class="iocdi.Person"> <lookup-method name="createArrow" bean="Arrow" /> </bean> </beans>
最后測(cè)試一下,控制臺(tái)查看一下:
先說一下,分隔線前面之所以會(huì)輸出false是因?yàn)閯?chuàng)建的兩個(gè)對(duì)象的引用不同,雖然這里打印出來是eeeeArrow和ddddArrow結(jié)果確實(shí)不同,因?yàn)槭请S機(jī)的,即便有可能結(jié)果相同,兩個(gè)對(duì)象的引用也不相同。但是分隔線下面無論如何創(chuàng)建的兩個(gè)對(duì)象的引用相同。大家也可能會(huì)疑惑,為什么在配置文件里配置的抽象類也可以實(shí)例化對(duì)象,并且抽象類中的抽象方法createArrow()并沒具體實(shí)現(xiàn)卻可以創(chuàng)建Arrow實(shí)例,這里就跟Spring容器有關(guān),其具體實(shí)現(xiàn)了abstarct類,如果createArrow()不是抽象方法,那abstract實(shí)現(xiàn)類也會(huì)覆蓋這個(gè)方法。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注