spring配置檔案中autowire詳解
這個屬性對應的值有以下幾種
常用的是byName和byType,我來具體說說這兩種值的區別與作用。
例項(DAO、Implements、Service三者之間的關係)
public class UserDAOImpl implements UserDAO{ private int daoId; public int getDaoId() { return daoId; } public void setDaoId(int daoId) { this.daoId = daoId; } @Override public String toString() { // TODO Auto-generated method stub return "daoId="+daoId; } }
public class UserService { private UserDAO userDAO = new UserDAOImpl(); public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } public void add(User user) { this.userDAO.save(user); } }
public class SpringTest { @Test public void testAdd() throws Exception{ ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans.xml"); UserService userService=(UserService) applicationContext.getBean("userService"); System.out.println(userService.getUserDAO()); } }
daoId作用
之所以設定了個daoId變數,是為了在自動裝配時,判斷到底是哪個bean被裝配了。檢視daoId變數值即可知道。重寫toString方法是為了輸出daoId的值
byName
顧名思義,即通過名字來自動裝配。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userDAOImpl1" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="1"></property>
</bean>
<bean id="userDAOImpl2" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="2"></property>
</bean>
<bean id="userService" class="com.service.UserService" scope="prototype" autowire="byName">
</bean>
</beans>
可以看到,我們設定了2個UserDOAImpl的bean,取名為userDAOImpl1與userDAOImpl2加以區分,並且賦值2個daoId的變數值分別為1和2。那麼這裡的byName到底是指哪裡的name呢?是指UserService當中UserDAOImpl的物件名,通過我們例項中的程式碼可以看到,物件名為userDAO,可是這2個bean都不是這個名字。所以執行的結果為
daoId=0
所以,如果想使用byName值,必須有一個id為userDAO的bean,才能被自動裝配。現在我們做如下修改:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userDAO" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="1"></property>
</bean>
<bean id="userDAOImpl2" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="2"></property>
</bean>
<bean id="userService" class="com.service.UserService" scope="prototype" autowire="byName">
</bean>
</beans>
檢視輸出結果
daoId=1
byType
現在,我們將配置檔案進行修改
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userDAOImpl1" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="1"></property>
</bean>
<bean id="userDAOImpl2" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="2"></property>
</bean>
<bean id="userService" class="com.service.UserService" scope="prototype" autowire="byType">
</bean>
</beans>
執行檢視結果
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService' defined in class path resource [beans.xml]:
Unsatisfied dependency expressed through bean property 'userDAO': : No qualifying bean of type [com.dao.UserDAO] is defined: expected single matching bean
but found 2: userDAOImpl1,userDAOImpl2; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of
type [com.dao.UserDAO] is defined: expected single matching bean but found 2: userDAOImpl1,userDAOImpl2
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1303)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1195)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956)
at com.test.SpringTest.testAdd(SpringTest.java:14)
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:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
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)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.dao.UserDAO] is defined: expected single matching bean but found 2: userDAOImpl1,userDAOImpl2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1288)
... 30 more
通過錯誤程式碼提示可以看到,spring找到了2個同類型的bean,所以無法判斷到底是哪個是使用者所需要的bean.現在我們只留下一個bean
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userDAOImpl1" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="1"></property>
</bean>
<bean id="userService" class="com.service.UserService" scope="prototype" autowire="byType">
</bean>
</beans>
執行檢視結果
daoId=1
通過例項程式碼可以知道,我們的UserService用的實現類是UserDAOImpl,並且只匹配到了一個對應的類,所以成功匹配。
總結:
byName是指在service中實現類的物件名
byType 是指在service中實現類的類名是否與bean的class一致
在實際開發中,並不建議使用自動裝配,因為需要小心謹慎,很容易出現問題。推薦使用手動裝配
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userDAOImpl1" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="1"></property>
</bean>
<bean id="userDAOImpl2" class="com.dao.impl.UserDAOImpl">
<property name="daoId" value="2"></property>
</bean>
<bean id="userService" class="com.service.UserService" scope="prototype">
<property name="userDAO" ref="userDAOImpl1"/>
</bean>
</beans>
這樣無論多少個相同型別的bean都不會出現問題。