• Spring技术内幕阅读笔记(一)


    1.BeanFactory:实现ioc容器的最基本形式。
    String FACTORY_BEAN_PREFIX = "&";
    Object getBean(String var1) throws BeansException;指定名字的bean

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;byType

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    boolean containsBean(String var1);是否包含指定名字的bean

    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    是否为单例bean
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    是否为原型bean
    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
    查询指定名字的bean的class类型是否是特定的Class类型
    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    获取指定名字bean的Class类型
    String[] getAliases(String var1);获取指定名字bean的所有别名
    XmlBeanFactory:
    public class XmlBeanFactory extends DefaultListableBeanFactory {
    private final XmlBeanDefinitionReader reader;

    public XmlBeanFactory(Resource resource) throws BeansException {
    this(resource, (BeanFactory)null);
    }
    BeanDefination来源在resource里,
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
    super(parentBeanFactory);
    this.reader = new XmlBeanDefinitionReader(this);
    this.reader.loadBeanDefinitions(resource);
    }
    }
    编程式使用Ioc容器
    ClassPathResource res = new ClassPathResource("/applicationContext-core.xml");
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(res);
    1.1Ioc容器的初始化是调用refresh()方法来启动的,
    这个启动包括三个过程:1.BeanDefination的Resource定位2.载入3.注册
    1).Resource定位:指的是BeanDefination的资源定位,寻找数据的过程。由ReaourceLoader通过统一的Resource接口来完成。
    2).BeanDefination的载入。载入过程就是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个数据结构就是BeanDefination.
    3).向Ioc容器注册这些BeanDefination的过程。这个过程是通过调用BeanDefinatinRegistry接口的实现来完成的。是把载入过程中的BeanDefination向Ioc容器进行注册,在Ioc容器内部将BeanDefination注入到一个HashMap里,Ioc容器就是通过这个HashMap持有这些BeanDefination数据。

    载入和依赖注入区别:
    依赖注入一般发生在应用第一次通过getBean向容器索取bean的时候,但是有一个例外就是可以对Bean设置lazyinit属性来完成bean的依赖注入,使其在初始化阶段就完成了。而不必要等到整个初始化完成以后,第一次getBean时才出发。
    1.2 BeanDefiantion的Resource定位。
    在ApplicationContext中Spring已经为我们提供了一系列加载不同Resource的读取器的实现,比如FileSystemXmlApplicationContext,ClassPathXmlApplicationContext,Xml
    WebApplicationContext可以从文件系统,Class Path 或者web容器中载入Resource。

    public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
    public FileSystemXmlApplicationContext() {
    }

    public FileSystemXmlApplicationContext(ApplicationContext parent) {
    super(parent);
    }
    //该构造函数的configLocation包含的是BeanDefination所在的文件路径
    public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[]{configLocation}, true, (ApplicationContext)null);
    }
    //该构造函数的configLocation包含多个BeanDefination所在的文件路径
    public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
    this(configLocations, true, (ApplicationContext)null);
    }
    //指定自己的双亲Ioc容器
    public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
    this(configLocations, true, parent);
    }

    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
    this(configLocations, refresh, (ApplicationContext)null);
    }
    //调用refresh方法启动了BeanDefination的载入过程
    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
    super(parent);
    this.setConfigLocations(configLocations);
    if(refresh) {
    this.refresh();
    }

    }

    protected Resource getResourceByPath(String path) {
    if(path != null && path.startsWith("/")) {
    path = path.substring(1);
    }

    return new FileSystemResource(path);
    }
    }
    1.3BeanDefination的载入和解析
    载入过程:把定义的BeanDefination在Ioc容器中转换为一个Spring内部表示的数据结构的过程,这些BeanDefination数据在Ioc容器中通过一个HashMap来维护和保持。
    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
    super(parent);
    this.setConfigLocations(configLocations);
    //这里调用容器的refresh,是载入BeanDefination的入口
    if(refresh) {
    this.refresh();
    }
    }
    容器的启动设计的很重要的方法refresh,在AbstractApplicationContext里,详细描述了ApplicationContext初始化的过程,比如BeanFactory的更新,MessageSource和PostProcessor的注册等等。
    public void refresh() throws BeansException, IllegalStateException {
    Object var1 = this.startupShutdownMonitor;
    synchronized(this.startupShutdownMonitor) {
    this.prepareRefresh();
    ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
    this.prepareBeanFactory(beanFactory);
    try {
    //设置BeanFactory的后置处理
    this.postProcessBeanFactory(beanFactory);
    //调用BeanFactory的后处理器
    this.invokeBeanFactoryPostProcessors(beanFactory);
    //注册Bean的后置处理器,在Bean创建过程中调用
    this.registerBeanPostProcessors(beanFactory);
    //对上下文的消息源进行初始化
    this.initMessageSource();
    //初始化上下文事件机制
    this.initApplicationEventMulticaster();
    //初始化其他的特殊Bean
    this.onRefresh();
    //检查监听Bean并且把这些Bean向容器注册
    this.registerListeners();
    //实例化所有的non-lazy-init的单件
    this.finishBeanFactoryInitialization(beanFactory);
    //发布容器时间,结束refresh过程
    this.finishRefresh();
    } catch (BeansException var9) {
    if(this.logger.isWarnEnabled()) {
    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
    }
    //为防止Baen资源占用,在异常处理中,销毁已经在前面生成的单件Bean
    this.destroyBeans();
    this.cancelRefresh(var9);
    throw var9;
    } finally {
    this.resetCommonCaches();
    }
    }
    }
    在refreshBeanFactory中,如果已经有容器存在则需要销毁和关闭。
    不同形式的BeanDefination使用不同的BeanDefinationReader来完成数据的载入工作.
    对于xml文件bean的property属性的解析,解析结果放到PropertyValue中,然后设置到BeanDefinationHolder中去。
    1.4BeanDefination在Ioc容器中的注册
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
    将解析得到的BeanDefination向Ioc容器的beanDefinationMap注册的过程是在载入BeanDefination完成后进行的。
    首先DefaultListableBeanFactory实现了BeanDefinationRegistry接口,这个接口的实现完成了BeanDefination向容器的注册,注册过程不复杂,就是把BeanDefination设置到HashMap中去,需要注意的是,遇到同名的beanDefination需要允许覆盖。
    注册BeanDefination过程
    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    //获取beanName
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    String[] aliases = definitionHolder.getAliases();
    if(aliases != null) {
    String[] var4 = aliases;
    int var5 = aliases.length;
    //
    for(int var6 = 0; var6 < var5; ++var6) {
    String alias = var4[var6];
    registry.registerAlias(beanName, alias);
    }
    }

    }

    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 var9) {
    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
    }
    }
    BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
    if(oldBeanDefinition != null) {
    if(!this.isAllowBeanDefinitionOverriding()) {
    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
    }
    if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
    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 + "]");
    }
    this.beanDefinitionMap.put(beanName, beanDefinition);
    } else {
    if(this.hasBeanCreationStarted()) {
    Map var4 = this.beanDefinitionMap;
    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 {
    //注册BeanDefination的过程,把beanName存到beanDefinitionNames的同时,把beanName作为Map的key,把BeanDefination做为value存到BeanDefinationMap中
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
    this.manualSingletonNames.remove(beanName);
    }
    this.frozenBeanDefinitionNames = null;
    }
    if(oldBeanDefinition != null || this.containsSingleton(beanName)) {
    this.resetBeanDefinition(beanName);
    }

  • 相关阅读:
    php之工厂模式
    PHP 给GIF 缩略图实例代码
    WGS84 Mercator project转换的算法(C#)
    .net Enum用法
    Google Maps API编程资源大全
    结对作业
    使用Lightbox制作照片条
    使用css3中transition的页面切换
    使用css3中transition的页面切换(继续创新版)
    iframe中父窗口获取子窗口的元素
  • 原文地址:https://www.cnblogs.com/alliswelltome/p/7183301.html
Copyright © 2020-2023  润新知