IOC, 即控制反转(Inversion of Control), 它的主要作用是用来解耦。 举个例子来说: 古代的皇帝再临幸妃子的时候, 他不会自己去找妃子, 而是告诉太监, 今天要哪个妃子, 然后太监去将皇帝指定的妃子抬到皇帝的住处, 这个过程就是控制反转。 对应我们的程序来说, 皇帝就是调用类, 妃子就是被调用对象, 而太监就是我们要讲到的IOC容器。
v3.2.12.RELEASE下载地址: http://pan.baidu.com/s/1bngzhUn
v4.1.5.RELEASE下载地址:http://pan.baidu.com/s/1kTnAxqn
spring-tool-suite-3.6.4.RELEASE-e4.4.2-win32-x86_64下载地址: http://pan.baidu.com/s/1bnvsnqZ
本文使用spring3.2, 下载解压后的目录如:
执行import-into-eclipse.bat, 根据提示一步一步走完, 这个时候需要下载一些东西, 需要等待一会, 执行完成后目录结构如下:
打开spring-tool-suite, 按照import-into-eclipse中的提示导入程序。
新建一个java工程, 完成后在buildpath中做如下设置:
图中各类代码如下:
public class Start {
public static void main(String[] args) {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext("org.spring");
System.out.println(appContext.getBean("userDao"));
System.out.println(new UserService().load().getUsername());
System.out.println("end");
}
}
public class UserService {
@Autowired
private UserDao userDao;
public User load() {
User user = userDao.load();
return user;
}
}
@Component
public class UserDao {
public User load() {
User user = new User("zhangsan", 11);
return user;
}
}
public class User {
private String username;
private Integer age;
public User(String username, Integer age) {
super();
this.username = username;
this.age = age;
}
……getter、setter省略
}
启动程序, 进入AnnotationConfigApplicationContext类, 我们发现这个类继承了GenericApplicationContext, 间接继承了AbstractApplicationContext。而AbstractApplicationContext则实现了ApplicationContext接口, ApplicationContext接口最终继承了BeanFactory接口。这些继承关系用类图表示如下:
这里我们先介绍几个spring中的基础接口:
BeanFactory Bean抽象工厂的最顶层抽象接口, 所有BeanFactory、ApplicationContext都实现了这个接口
FactoryBean 工厂类的顶层抽象接口, 所有的Factory实例都实现了它
BeanDefinition Bean定义类, 熟悉spring的同学都知道spring配置文件里面我们会定义很多bean, 那些bean最终在spring程序中的体现就是BeanDefinition了
不过需要注意BeanDefinition并不是bean实例, 它只是bean的定义信息, 包括className、scope、parent、ref等等信息, 真正注入的时候会从缓存或具体的工厂方法获取或生成实例对象。
好了, 回到AnnotationConfigApplicationContext这个类的构造方法:
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
} 这里定义了一个reader、一个scanner, 这两个实际上只会使用一个, 具体使用哪个是根据我们传入的参数决定的, 例如在我们的例子中传入的是一个包名, 那么实际调用的就是scanner。
从这里, 我们可以很明显的看出scan方法完成的工作, 即扫描给定包下的所有类, 实际上我们跟踪代码后发现确实如此。
一步一步跟踪进去, 发现最终执行扫描过程的是ClassPathBeanDefinitionScanner类的doScan方法:
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
beanDefinitions这个集合类实例存的就是扫描出的bean定义
findCandidateComponents(basePackage) 这个方法就是扫描出所有的bean定义
循环体中checkCandidate方法调用之前的部分一直在为bean定义填充信息, 只有在checkCandidate验证通过后, 才会真正调用注册方法registerBeanDefinition(definitionHolder, this.registry);
我们看到这里传入的第二个参数是this.registry, 那么这个参数到底是什么呢?
我们看AnnotationConfigApplicationContext的构造方法中this.scanner = new ClassPathBeanDefinitionScanner(this)这条语句, 可以发现registry就是从这里传入的一个BeanDefinitionRegistry对象, 我们发现他的父类GenericApplicationContext实现了BeanDefinitionRegistry接口, 并且它有一个私有的DefaultListableBeanFactory对象变量, 可见构造方法中的this确实是AnnotationConfigApplicationContext对象本身。
一路跟踪后, 我们发现代码最终到DefaultListableBeanFactory类
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
synchronized (this.beanDefinitionMap) {
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName +
"‘: There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean ‘" + beanName +
"‘: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
} beanDefinitionMap 这个变量的定义为
/** Map of bean definition objects, keyed by bean name */ private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);他就是真正的Bean定义类存放的地方。 并且在注册bean定义的时候还会根据allowBeanDefinitionOverriding这个属性的值来判断是否允许覆盖同名bean, 但是在3.2中这个属性默认是无法设值得, 如果我们要改动他的值, 只能通过继承, 添加set方法来实现。
到这里IOC容器加载Bean定义的过程就结束了, 接下来我会再起一篇博文, 详细介绍IOC的注入过程, 包括单例对象、懒加载等的处理过程。
原文:http://my.oschina.net/xiaoqqq/blog/390192