一:依賴注入
通過第一個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();
}
}
比如:在已經使用了註解的方式的前提下,然後又在配置文件中加上對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會報錯。