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的注入过程, 包括单例对象、懒加载等的处理过程。