Spring IOC(XML和註解)

      一:依賴注入 

      通過第一個Spring程序之後,創建對象的工作會交給Spring來完成,只需要在配置文件上配置相關的<bean>節點,通過Spring容器就可以根據配置創建對象。

       回顧上一個spring配置文件:

        <bean name="UserDao" class="yzr.dao.UserDao" ></bean>
	<bean name="UserService" class="yzr.service.UserService" >
		<property name="userDao" ref="UserDao"></property>
	</bean>
	<bean name="UserAction" class="yzr.action.UserAction" >
		<property name="userService" ref="UserService"></property>
	</bean>
      這種是通過屬性方式的依賴注入,在<bean>節點內包含<property>節點,指定相應的依賴關係。在這種情況下,在Service中需要聲明一個關於UserDao的set方法,就像這樣:

package yzr.service;

import yzr.dao.UserDao;

public class UserService {
	private UserDao userDao=null;
	public void setUserDao(UserDao userdao){
		userDao=userdao;
	}
	public void run(){
		userDao.run();
		System.out.println("Service執行Run");
	}
}
注意的地方是,<property name="userDao" ref="UserDao"></property>中name的值爲userDao,與Service類中的屬性變量userDao必須一致,注意大小寫。

     除了上面這種通過屬性依賴注入的方式,還有另外一種通過構造函數注入依賴,使用<constructor-arg>節點。

        <bean name="UserDao" class="yzr.dao.UserDao" ></bean>
	<!-- 
	<bean name="UserService" class="yzr.service.UserService" >
		<property name="userDao" ref="UserDao"></property>
	</bean>
	-->
	<bean name="UserService" class="yzr.service.UserService" >
		<constructor-arg ref="UserDao"></constructor-arg>
	</bean>
	<bean name="UserAction" class="yzr.action.UserAction" >
		<property name="userService" ref="UserService"></property>
	</bean>
      通過構造函數注入的話,Service需要提供一個帶依賴類型的構造函數,比如這樣:

package yzr.service;

import yzr.dao.UserDao;

public class UserService {
	private UserDao userDao=null;
	/*
	public void setUserDao(UserDao userdao){
		userDao=userdao;
	}
	*/
	public void run(){
		userDao.run();
		System.out.println("Service執行Run");
	}
	
	public UserService(){
		
	}
        public UserService(UserDao userDao){
    	       this.userDao=userDao;
	}
}

      通過上面兩個例子可以往被創建對象注入值(或者對象),此外,假若當需要注入的依賴爲集合或者map類型時,spring也提供了相應的節點配置,下面使用屬性注入方式說明:

      1.注入List集合:

      1)將String類型值注入集合中用value節點

      <bean name="UserAction" class="yzr.action.UserAction" >
		<property name="userService" ref="UserService"></property>
		<property name="stringList">
                    <list>
                        <value>YZR</value>
                    </list>
                 </property>
	</bean>
      相應的Action中聲明一個stringList屬性變量:

        private List stringList=null;
	public void setStringList(List actionList) {
		this.stringList = actionList;
	}
      2)將對象類型注入集合中,使用bean節點

       <property name="beanList">
                    <list>
                    	<bean id="Userbean" class="yzr.entity.UserBean">
	  	               <property name="name" value="YZR"></property>
	                </bean>
                    </list>
        </property>
     
      相應的Action中聲明一個beanList屬性變量:

        private List beanList=null;
	public void setBeanList(List beanList) {
		this.beanList = beanList;
	}
      3)使用ref注入已有的bean
 <bean name="UserAction" class="yzr.action.UserAction" >
		
        <property name="beanList">
                    <list>
                    	<ref bean="Userbean"/>
                    	
                    </list>
        </property>
</bean>
<bean id="Userbean" class="yzr.entity.UserBean">
     <property name="name" value="YZR"></property>
</bean>

    2.注入Map鍵值對:

    同理 與List,下面三種方式就寫在一起表示:

        <property name="maps">
            <map>
                <entry key="StringKey" value="1" />
                <entry key="BeanKey" value-ref="Userbean" />
                <entry key="BeanKey2">
                    <bean id="Userbean" class="yzr.entity.UserBean">
	  	        <property name="name" value="YZR"></property>
	            </bean>
                </entry>
            </map>
        </property>
    3.注入prop屬性文件的鍵值對:

    propertise屬性文件的內容只能是文本類型的鍵值對,所以在prop節點內寫上文本即可。

       <property name="pros">
            <props>
                <prop key="StringKey">StringValue</prop>
            </props>
        </property>
      二 P命名空間

    spring IOC容器在創建對象的時候,很多場景需要注入依賴,在使用屬性方式注入時,編寫property節點會很常用,爲了簡化配置文件關於property的寫法,spring提供了P名稱空間:   

xmlns:p="http://www.springframework.org/schema/p"
在編寫bean節點的時候,可以使用 p:屬性變量=值     
        <!--String類型注入-->
        <bean id="user" class="yzr.entity.UserBean" p:name="StringValue"></bean>
        <!--Bean對象注入-->
	<bean id="user" class="yzr.entity.UserBean" p:myBean-ref="BeanId"></bean>
      三  spring註解

     使用註解的方式來簡化使用配置文件方式創建對象的過程:

           @Repository 在持久層使用     (dao)
           @Service    在業務邏輯層使用 (service)
           @Controller 在控制層使用     (action)

           @Component  把對象加入IOC容器,都可以使用這個註解 (通用)

           @Resource   注入屬性值: 從容器中找指定名稱的對象,如果沒有指定名稱,用修飾的成員變量名稱!

     Dao:

package yzr.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {
	public void run(){
		System.out.println("UserDao執行Run;");
	}
}
     Service:

package yzr.service;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import yzr.dao.UserDao;
@Service
public class UserService {
	@Resource
	private UserDao userDao=null;
	/*
	public void setUserDao(UserDao userdao){
		userDao=userdao;
	}
	*/
	public void run(){
		userDao.run();
		System.out.println("Service執行Run");
	}
	
	public UserService(){
		
	}
}
      Action:
        
package yzr.action;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;

import yzr.service.UserService;
@Controller
public class UserAction {
	@Resource
	private UserService userService=null;
	
	
	public String execute() throws Exception{
		userService.run();
		System.out.println("UserAction執行execute");
		//System.out.println(stringList);
		//System.out.println(beanList);
		return "success";
	}
}
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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    	 http://www.springframework.org/schema/beans/spring-beans.xsd
     	 http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">
     	 
    <context:component-scan base-package="yzr"></context:component-scan>	 
	
	
	
</beans>   
測試:

package yzr.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;

import yzr.action.UserAction;

public class app {
	String path="ApplicationContext.xml";
	@Test
	public void test() throws Exception{
		ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext(path);
		System.out.println("加載配置文件完成");
		
		//UserAction action=(UserAction) ac.getBean("UserAction");
		//action.execute();
		
		UserAction action =null;
		action=ac.getBean(UserAction.class);
		action.execute();
	}
}


注意:當使用xml配置和使用註解兩種方式一起使用的時候,如果當spring IOC容器在創建對象的時候匹配到兩個或以上的時候會報錯。

比如:在已經使用了註解的方式的前提下,然後又在配置文件中加上對UserAction的bean:

<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    	 http://www.springframework.org/schema/beans/spring-beans.xsd
     	 http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">
     	 
    <context:component-scan base-package="yzr"></context:component-scan>	 
    <bean name="UserAction" class="yzr.action.UserAction" ></bean>
</beans>     
package yzr.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;

import yzr.action.UserAction;

public class app {
	String path="ApplicationContext.xml";
	@Test
	public void test() throws Exception{
		ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext(path);
		System.out.println("加載配置文件完成");
		
		//UserAction action=(UserAction) ac.getBean("UserAction");
		//action.execute();
		
		UserAction action =null;
		action=ac.getBean(UserAction.class);
		action.execute();
	}
}

當getBean(UserAction.class)時會報錯,報錯信息爲:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [yzr.action.UserAction] is defined: expected single matching bean but found 2: userAction,UserAction

at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:289)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1125)
at yzr.test.app.test(app.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


因爲使用註解的方式spring會自動創建一個UserAction對象,而在此時我們又手動在配置文件下又加上了一個UserAction類型的bean,所以使用getBean(UserAction.class)時spring容器創建對象時會找到兩個UserAction。需要去掉其中一個纔對。

所以,xml配置模式和註解在不衝突的條件下可以一起使用,但如果存在重複的時候spring會報錯。





發佈了55 篇原創文章 · 獲贊 64 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章