IoC是Inversion of Control的缩写,被称为控制反转。
IoC是Spring框架中其他功能的基础。因此,理解并能够熟练使用IoC是进一步学习Spring框架的必要前提。
例:
public class A{
private B b;
public void setB(B b){
this.b=b;
}
}
public class B{
private C c;
public void setC(C c){
this.c=c;
}
}
public class C{
}
上述代码中共有三个类,分别是A、B、C类。
其中A类的实例总是依赖一个B类的实例,而B类的实例总是依赖一个C类的实例。
因此要正常使用A类的实例,总需要如下所示的创建装配的过程:
C c = new C();
B b = new B();
b.setC(c);
A a = new A();
a.setB(b);
在实际应用中,类似这样的代码随处可见,A越是复杂,则对其装配的过程将越复杂。
为了能够更为直观地理解IoC,通过使用dbcp连接池的例子进行说明。
首先通过非IoC的方式装配使用BasicDataSource对象:
1、在工程中导入dbcp包
commons-dbcp.jar
commons-pool-1.3.jar
2、导入MySql驱动包
3、创建TestDbcp类,测试连接池
package test;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
public class TestDbcp {
public static void main(String[] args) {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mldn");
dataSource.setUsername("root");
dataSource.setPassword("password");
dataSource.setMaxActive(10);
dataSource.setInitialSize(2);
Connection con = null;
for(int i=0;i<15;i++){
try {
con=dataSource.getConnection();
System.out.println("connection "+i+" : "+con.hashCode());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
运行结果:
connection 0 : 14518194
connection 1 : 33018164
connection 2 : 32425490
connection 3 : 10430987
connection 4 : 9516880
connection 5 : 2765838
connection 6 : 10481519
connection 7 : 19883652
connection 8 : 27547574
connection 9 : 11403277
由于最大连接数为10,所以在没有释放当前连接前,将最多获得10个连接,不能再获得新的连接,当前线程将进入等待状态。
上述代码中,关键的对象是BasicDataSource,而要正确使用该对象,需要使用大量的setXXX方法,对其依赖的属性进行赋值。
IoC就是要将上述代码中生成BasicDataSource对象的过程交给容器实现,而不在代码中实现。
也就是说,以前是在代码中控制对象的生成和注入,而是用IoC后,就将设计好的类交给IoC容器,让IoC容器控制对象的生成和属性的注入,称为控制反转。
生成对象的过程,就是将对象依赖的属性进行注入的过程,因此IoC也被称为DI(Dependency Injection),即依赖注入。
IoC的使用
通过修改连接池的实例,使用IoC来装配BasicDataSource对象。
要使用IoC装配对象,就必须在Spring的配置文件(默认为applicationContext.xml)中进行配置。
配置信息如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/mldn</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>password</value>
</property>
<property name="maxActive">
<value>10</value>
</property>
<property name="initialSize">
<value>2</value>
</property>
</bean>
</beans>
<property>元素为bean装配属性,其中name是bean的类中setXXX方法的名字,如<property name="username">将调用setUsername()方法,
并将<value>的值root作为参数传递给setUsername方法对属性赋值。
在applicationContext.xml中配置了bean后,通过如下代码使用bean:
package test;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Testspr {
public static void main(String args[]){
ApplicationContext ctxt = new ClassPathXmlApplicationContext("applicationContext.xml");
BasicDataSource dataSource =(BasicDataSource)ctxt.getBean("dataSource");
Connection con =null;
for(int i=0;i<15;i++){
try {
con=dataSource.getConnection();
System.out.println("connection "+i+" : "+con.hashCode());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
运行结果:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
connection 0 : 10969598
connection 1 : 17984263
connection 2 : 26440236
connection 3 : 4098499
connection 4 : 8106640
connection 5 : 29131495
connection 6 : 14440411
connection 7 : 31401995
connection 8 : 20634710
connection 9 : 7579563
上述代码中首先创建了ClassPathXmlApplicationContext对象,该对象依据配置文件applicationContext.xml获得IoC容器的信息。
然后使用ClassPathXmlApplicationContext中的getBean方法获得id为dataSource的bean对象。
接下来就可以通过获得的bean对象来获得连接,使用数据库连接池。