spring Ioc(inversion of control) 是spring的核心,应用本身不负责依赖对象的创建和维护,依赖对象的创建和维护都交给外部容器,就是spring来完成。这样控制权就交给了外部容器,控制权的转移就是所谓控制反转。也叫DI(Dependency Injection),依赖注入。容器负责把依赖的具体对象注入到上层对象,而上层对象只需提供一个接口声明。
具体开发:
使用spring来完成依赖注入,完成对象的创建
1.创建web项目,导入需要的jar包
2.编写javabean
package sdibt.fly.entity;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3.在src目录下创建配置文件,applicationContext.xml
Bean标签有个scope属性,取值分别是singleton,prototype,request,session每一次采用spring框架获取javabean,方式分别是,永远一个实例,每次一个实例,每次请求一个实例,每次会话一个实例。
默认是singleton
<?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.xsd"
default-autowire="byName"
>
<!-- User实体类对象,id唯一标识这个对象 -->
<bean id="user" class="sdibt.fly.entity.User"></bean>
</beans>
4.编写Demo来用spring注入javabean
package sdibt.fly.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import sdibt.fly.entity.User;
public class TestIoc {
public static void main(String[] args) {
//加载配置文件
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过id来获取bean对象
User user = (User) ctx.getBean("user");
System.out.println(user.getUsername());
System.out.println(user.getPassword());
}
}
当然结果是两个null,不过没有抛出类型装换异常,证明确实是拿到了User类
源码剖析
接下来看一下spring是如何来完成对象的创建的。
获取bean是交给beanFactory来完成创建的
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
判断该类是否是单例的,继续跟进
try {
if (isSingleton(name)) {
return doGetSingleton(name, requiredType);
}
else {
return lookup(name, requiredType);
}
}
synchronized,单例获取对象,每次获取的都是用一个对象
this.singletonObjects.containsKey(name),首先会根据配置文件生成Map集合,这个配置文件在前面我们就已经加载好了,Map集合里面存放的是id及对应的类,在Map当中找到这个对应的id,根据id我们再获取这个类
最后把这个类返回
return (T) jndiObject;
private <T> T doGetSingleton(String name, Class<T> requiredType) throws NamingException {
synchronized (this.singletonObjects) {
if (this.singletonObjects.containsKey(name)) {
Object jndiObject = this.singletonObjects.get(name);
if (requiredType != null && !requiredType.isInstance(jndiObject)) {
throw new TypeMismatchNamingException(
convertJndiName(name), requiredType, (jndiObject != null ? jndiObject.getClass() : null));
}
return (T) jndiObject;
}
T jndiObject = lookup(name, requiredType);
this.singletonObjects.put(name, jndiObject);
return jndiObject;
}
}