//读取资源文件
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource("spring.xml");
//BeanDefinitionRegistry simpleBeanDefinitionRegistry = new SimpleBeanDefinitionRegistry();
//BeanDefinition注册器
BeanDefinitionRegistry simpleBeanDefinitionRegistry = new DefaultListableBeanFactory();
//BeanDefinition读取器
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(simpleBeanDefinitionRegistry);
//BeanDefinition读取器从资源文件读取BeanDefinition
beanDefinitionReader.loadBeanDefinitions(resource);
//注册BeanDefinition
BeanDefinition rootBeanDefinition = new RootBeanDefinition(IOCConfig.class);
simpleBeanDefinitionRegistry.registerBeanDefinition("test", rootBeanDefinition);
System.out.println(Arrays.toString(simpleBeanDefinitionRegistry.getBeanDefinitionNames()));
System.out.println(((DefaultListableBeanFactory) simpleBeanDefinitionRegistry).getBean("test"));
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class);
registry.registerBeanDefinition("user", rootBeanDefinition);
}
}
@ComponentScan("gdut.ff.ioc")
@Import(MyImportBeanDefinitionRegistrar.class)
public class TestIoC {
public static void main(String[] args) {
//注解方式
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestIoC.class);
System.out.println(context.getBean(IOCConfig.class));
System.out.println(context.getBean("user"));
}
}
注册一个BeanDefinition,并修改BeanDefinition的class类型。
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition rootBeanDefinition = new RootBeanDefinition(IOCConfig.class);
registry.registerBeanDefinition("test", rootBeanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("test");
beanDefinition.setBeanClassName("gdut.ff.ioc.User");
}
}
AnnotationConfigApplicationContext调用了它自己的无参构造函数,AnnotationConfigApplicationContext继承了GenericApplicationContext类,GenericApplicationContext的无参构造函数是实例化一个DefaultListableBeanFactory对象。DefaultListableBeanFactory就是一个Bean工厂。
DefaultListableBeanFactory有以下重要的属性:
//key是bean的名称,value是BeanDefinition对象
private final Map beanDefinitionMap = new ConcurrentHashMap(256);
//以注册的顺序,存放BeanDefinition的名称
private volatile List beanDefinitionNames = new ArrayList(256);
再来看看BeanDefinition接口:
BeanDefinition是用来装配Bean的属性的。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
......
}
//注解方式
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestIoC.class);
BeanFactory defaultListableBeanFactory = context.getDefaultListableBeanFactory();
BeanDefinition rootBeanDefinition = new RootBeanDefinition(IOCConfig.class);
((DefaultListableBeanFactory) defaultListableBeanFactory).registerBeanDefinition("config", rootBeanDefinition);
System.out.println(context.getBean("config"));
//实例化非懒加载单例Bean
finishBeanFactoryInitialization(beanFactory);
创建bean之前,会先去单例对象池(singletonObjects)中获取
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//先从单例缓存中找
Object singletonObject = this.singletonObjects.get(beanName);
//没有找到先判断是否是正在创建的bean
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//earlySingletonObjects保存所有提前曝光(还没有进行属性注入)的实例,
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//如果允许早期依赖,可以尝试从singletonFactories中找到对应的单例工厂
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
//注册到singletonMap
((DefaultListableBeanFactory) defaultListableBeanFactory).registerSingleton("config", new IOCConfig());
进入DefaultListableBeanFactory的registerSingleton方法
再进入DefaultSingtonBeanRegistry的registerSingleton方法
进入DefaultSingtonBeanRegistry的addSingleton方法,将注册的单例添加到单例对象池中
调用BeanUtils的instantiateClass方法进行反射实例化。
@Component
public class MyFactoryBean implements FactoryBean {
@Override
public User getObject() throws Exception {
return new User();
}
@Override
public Class> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
System.out.println(context.getBean("myFactoryBean"));//返回结果是:gdut.ff.ioc.User@c8e4bb0
System.out.println(context.getBean("&myFactoryBean"));//返回结果是:gdut.ff.ioc.MyFactoryBean@6279cee3
为什么FactoryBean的名称前面加个&,返回的就是FactoryBean实例,不加&,返回的就是FactoryBean的Object实例呢?
调用AbstractBeanFactory的getObjectForBeanInstance判断一个Bean是否是FactoryBean。
在getObjectForBeanInstance方法中,如果name是以&开头的就直接返回FactoryBean实例。
String FACTORY_BEAN_PREFIX = "&";
如果不是"&"开头的,调用FactoryBeanRegistrySupport 的doGetObjectFromFactoryBean方法,最后的返回值是FactoryBean的getObject方法的内容。