1. 程式人生 > >spring配置檔案中autowire詳解

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都不會出現問題。