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