天天看點

Spring依賴注入的兩種方式

Spring的核心之一就是IoC(Inversion of Control,控制反轉),或者說是DI(Dependency Injection,依賴注入)。那麼IoC和DI是同一個概念嗎?

其實它們是對同一件事情的不同描述。控制反轉是從容器的角度進行描述:容器控制應用類,由容器反向地向應用類注入應用類所需要的外部資源。依賴注入則是從應用類的角度進行描述:應用類依賴容器建立并注入它所需要的外部資源。

注:有說法認為IoC除了DI,還包括DL(Dependency Lookup,依賴查找):容器提供回調接口和上下文環境給元件。這裡不做贅述。

Spring依賴注入的兩種常見方式有Setter注入和構造器注入。

注:有說法認為還有接口注入的方式,但筆者沒有認識,故略去。

Setter方法注入

先看mybatis.xml裡的sqlSessionFactory配置:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="typeAliasesPackage" value="com.roger.practice.entity" />
        <property name="mapperLocations" value="classpath*:mapper/**/*.xml" />
        <property name="plugins">
            <array>
                <bean class="com.roger.mybatis.page.interceptor.PageInterceptor" />
                <bean class="com.roger.mybatis.page.interceptor.PageSqlRewriteInterceptor">
                    <property name="dialect" value="oracle" />
                </bean>
            </array>
        </property>
    </bean>
           

再聯系org.mybatis.spring.SqlSessionFactoryBean類中setMapperLocations方法:

public void setMapperLocations(Resource[] mapperLocations) {
      this.mapperLocations = mapperLocations;
    }
           

IoC容器會自動調用SqlSessionFactoryBean類中的setMapperLocations方法,将classpath下mapper檔案夾下的所有xml檔案塞到數組mapperLocations中。

構造器注入

先看dataSource.xml裡的jedisPool配置:

<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="poolConfig" />
        <constructor-arg name="host" value="192.168.0.12" />
        <constructor-arg name="port" value="6379" />
        <constructor-arg name="timeout" value="5000" />
        <constructor-arg name="password" value="rogerchen" />
        <constructor-arg name="database" value="12" />
    </bean>
           

再聯系redis.clients.jedis.JedisPool類中的構造器:

public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,
        int timeout, final String password, final int database) {
      this(poolConfig, host, port, timeout, password, database, null);
    }
           

這裡的注入方式是在JedisPool的構造函數中注入,也就是說在建立JedisPool對象時要将poolConfig、host、port、timeout、password和database等六個參數值傳進來。

總結

這樣一看,xml檔案中的最大差別是,setter注入使用property标簽,而構造器注入使用constructor-arg标簽,ref屬性都指向相應bean标簽的name屬性。若注入對象中沒有setter方法的實作,則使用構造器注入的方式。通過Spring建立的對象預設都是單例的,如果需要建立多執行個體對象可以在bean标簽裡添加一個屬性:

<bean name="..." class="..." scope="prototype">