前言
Ioc容器作为spring的核心部分,希望通过学习其源码来了解Ioc运作机制。为了学习的方便,在此去掉那些复杂的xml和注解解析,而是全部使用Java代码的方式来学习它的运作机制。
使用Ioc时,我们一般有两种方式:
- BeanFactory
- ApplicationContext
两者的区别在前者更多是使用在懒加载的场景下,而后者则是非懒加载的方式,在这里我们先学习第一种的实现方式。
Example
public class BeanFactoryIoc {
public static void main(String[] args) {
//1、创建个bean工厂
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//2、创建一个bean的定义
GenericBeanDefinition bd = new GenericBeanDefinition();
//定义属性
MutablePropertyValues mpvs = new MutablePropertyValues();
PropertyValue pv = new PropertyValue("name","Cat");
mpvs.addPropertyValue(pv);
//设置bean的类型和属性
bd.setPropertyValues(mpvs);
bd.setBeanClass(Animal.class);
//3、将定义好bean注册到容器
beanFactory.registerBeanDefinition("animal", bd);
beanFactory.preInstantiateSingletons();
//4、使用bean
Animal animal = (Animal) beanFactory.getBean("animal");
animal.say();
}
public static class Animal {
private String name;
public Animal() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void say(){
System.out.println("Hello " + name);
}
}
}
BeanDefinition
BeanDefinition与Bean区别:前者是用来定义Bean的(Bean是什么类型的,属性有哪些,属性值又是什么),而后者则是Bean本身。
从第2步看起,GenericBeanDefinition是bean的基本定义,如下是它的主要结构(省略了部分的继承关系及实现的接口),看下AbstractBeanDefinition,beanClass是bean是 属于哪种类型,propertyValuess是bean的属性集,里面定义了bean的属性名称及其值。通过知道一个bean是什么类型及bean的属性就可以确定定义下bean了。源码如下:
public class GenericBeanDefinition extends AbstractBeanDefinition{
}
public abstract class AbstractBeanDefinition implements BeanDefinition{
private volatile Object beanClass;
private MutablePropertyValues propertyValues;
}
public class MutablePropertyValues {
private final List<PropertyValue> propertyValueList;
}
public class PropertyValue {
private final String name;
private final Object value;
}
BeanDefinition的注册
第3步则时将BeanDefinition注册到bean工厂中,由bean工厂来管理bean。来看下DefaultListableBeanFactory的继承关系,registerBeanDefinition方法是在接口BeanDefinitionRegistry里面声明的。源码如下:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
//key为bean的名称,value为bean的具体定义,仅仅是定义,而非实例化好的对象
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//bean的名称列表
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
//根据类型获取bean实例,在单例模式下,该bean实例已经创建过则获取已经创建的,否则重新创建一个bean
public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBean(requiredType, (Object[]) null);
}
@Override
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
BeanFactory parent = getParentBeanFactory();
if (parent != null) {
return (args != null ? parent.getBean(requiredType, args) : parent.getBean(requiredType));
}
throw new NoSuchBeanDefinitionException(requiredType);
}
//注册bean的定义
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");
//校验BeanDefinition是否合法
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;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
//判断BeanDefinition是否注册过
if (oldBeanDefinition != null) {//已注册过,则输出一些日志,并覆盖原有的BeanDefinition
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
//覆盖已注册的BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {//没有注册过,则将新的BeanDefinition添加进去
if (hasBeanCreationStarted()) {//已启动状态,使用CopyAndWrite思想注册新的BeanDefinition
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {//如果还是开始状态,则直接注册,不需要锁
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
}
//非懒加载方式实例化bean
@Override
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
//遍历BeanDefinition,将符合条件的bean全部实例化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
//非懒加载的方式实例化bean同样也是调用getBean方法
getBean(beanName);
}
}
}
}
}
注册时整个代码重点其实就是this.beanDefinitionMap.put(beanName, beanDefinition);这一行代码。因为注册时只是把bean的信息注册,而不是把bean实例注册,所以,在这个代码段里,BeanFactory的注册BeanDefinition是一种懒加载的方式,因为此时并没有实例化bean,只有需要到bean具体实例的时候才实例化bean,并提供给外部使用。
当然,BeanFactory也有非懒加载的方式,当使用非懒加载方式时,需要我们在获取bean之前先调用preInstantiateSingletons()方法,它跟懒加载方式获取bean都是调用getBean()方法,该方法调用时会将bean实例化并缓存一起来,只不过它是预先调用而已。
总结
整个流程其实就两步:
- BeanDefinition注册
- 根据BeanDefinition生成Bean实例
引用BeanDefinition的注册,而不是注册Bean实例,Ioc容器可以根据Bean的作用域灵活地生成单例Bean,还是非单例的。同时还能灵活的的解决了是否使用懒加载的方式。
ApplicationContext也是Ioc容器的实现,只不过它实现了更多更强大的功能,且是非懒加载的方式而已,它的底层实现其实还是BeanFactory,后文再做分析。
网友评论