天天看点

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">