参考

控制反转是思想 依赖注入是实现

* 正转 new Object
* 反转 容器帮我们查找及注入依赖对象 对象只是被动的接受依赖对象

依赖注入(xml 和 java config)

* 通过构造方法或者set方法
* 基于设值函数的依赖注入(创建bean后调用bean的设值函数)
* 注入集合
* 自动装配
	* autowire byName byType constructor
	* 注解
		* @Required(属性setter方法 xml配置)
		* @Autowired(setter方法 非setter方法 构造函数和属性)
		* @Qualifier(两个实习类的时候做区分)
		* JSR-250
			* @PostConstruct(初始化回调函数)
			* @PreDestroy(注释作为销毁回调函数的一个替代)
			* @Resource(by-name 字段 setter方法)
		* 基于Java的配置
			* @Configuration(表示这个类可以使用 Spring IoC 容器作为 bean 定义的来源)
			* @Bean(支持初始化和销毁的回调方法)
			* @import(允许从另一个配置类中加载@Bean定义)

BeanFactory

在这里插入图片描述
那为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有它使用的场合,它主要是为了区分在Spring 内部在操作过程中对象的传递和转化过程时,对对象的数据访问所做的限制

  • ListableBeanFactory(可列表化的Bean)
  • HierarchicalBeanFactory(有继承关系的Bean)
  • AutowireCapableBeanFactory(定义Bean 的自动装配规则)

ApplicationContext

  • 1、支持信息源,可以实现国际化。(实现MessageSource 接口)
  • 2、访问资源。(实现ResourcePatternResolver 接口,后面章节会讲到)
  • 3、支持应用事件。(实现ApplicationEventPublisher 接口)

BeanDefinition

Bean 对象在Spring 实现中是以BeanDefinition 来描述的
在这里插入图片描述

BeanDefinitionReader

Bean 的解析主要就是对Spring 配置文件的解析。这个解析过程主要通过BeanDefintionReader 来完成
在这里插入图片描述

基于Xml 的IOC 容器的初始化

在这里插入图片描述

  • 寻找入口
    通过main()方法启动
    还有像AnnotationConfigApplicationContext 、FileSystemXmlApplicationContext 、XmlWebApplicationContext
    等都继承自父容器AbstractApplicationContext 主要用到了装饰器模式和策略模式,
    最终都是调用refresh()方法
  • 获得配置路径
  • 开始启动
    • refresh()是一个模板方法,规定了IOC 容器的启动流程
      在创建IOC 容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh 之后使用的是新建立起来的IOC 容器。
      它类似于对IOC 容器的重启,在新建立好的容器中对容器进行初始化,对Bean 配置资源进行载入。
@Override
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
            prepareRefresh();
            // Tell the subclass to refresh the internal bean factory.
            //2、告诉子类启动refreshBeanFactory()方法,Bean 定义资源文件的载入从
            //子类的refreshBeanFactory()方法启动
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // Prepare the bean factory for use in this context.
            //3、为BeanFactory 配置容器特性,例如类加载器、事件处理器等
            prepareBeanFactory(beanFactory);
            try {
                // Allows post-processing of the bean factory in context subclasses.
                //4、为容器的某些子类指定特殊的BeanPost 事件处理器
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
                //5、调用所有注册的BeanFactoryPostProcessor 的Bean
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
                //6、为BeanFactory 注册BeanPost 事件处理器.
                //BeanPostProcessor 是Bean 后置处理器,用于监听容器触发的事件
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
                //7、初始化信息源,和国际化相关.
                initMessageSource();
                // Initialize event multicaster for this context.
                //8、初始化容器事件传播器.
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
                //9、调用子类的某些特殊Bean 初始化方法
                onRefresh();
                // Check for listener beans and register them.
                //10、为事件传播器注册事件监听器.
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
                //11、初始化所有剩余的单例Bean
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                //12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
                finishRefresh();
            }
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                // Destroy already created singletons to avoid dangling resources.
                //13、销毁已创建的Bean
                destroyBeans();
                // Reset 'active' flag.
                //14、取消refresh 操作,重置容器的同步标识.
                cancelRefresh(ex);
                // Propagate exception to caller.
                throw ex;
            }
            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                //15、重设公共缓存
                resetCommonCaches();
            }
        }
}
  • 创建容器
    • 委派设计模式(父类定义抽象方法,调用子类容器实现的该方法) obtainFreshBeanFactory()方法调用子类容器的refreshBeanFactory()方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {  
		//这里使用了委派设计模式
		refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
	
//子类方法	
@Override
protected final void refreshBeanFactory() throws BeansException {        //如果已经有容器,销毁容器中的bean,关闭容器
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {//创建IOC 容器,其实这里就是创建了一个
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());            //对IOC 容器进行定制化,如设置启动参数,开启注解的自动装配等
            customizeBeanFactory(beanFactory);//调用载入Bean 定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions 方法,具体的实现调用子类容器        loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
}
  • 载入配置路径
  • 分配路径处理策略
  • 解析配置文件路径
  • 开始读取配置内容
  • 准备文档对象
  • 分配解析策略
  • 将配置载入内存
  • 载入元素
  • 总结(BeanDefinition 的Resource 定位、加载和注册这三个基本的过程)
    1、初始化的入口在容器实现中的refresh()调用来完成
    2、对Bean 定义载入IOC 容器使用的方法是loadBeanDefinition()
    通过ResourceLoader 来完成资源文件位置的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader 的实现
    ,可以从类路径,文件系统,URL 等方式来定为资源位置。如果是XmlBeanFactory 作为IOC 容器,那么需要为它指定Bean 定义的资源,
    也就是说Bean 定义文件时通过抽象成Resource 来被IOC 容器处理的, 容器通过BeanDefinitionReader 来完成定义信息的解析和Bean 信息的注册,
    往往使用的是XmlBeanDefinitionReader 来解析Bean 的XML 定义文件- 实际的处理过程是委托给BeanDefinitionParserDelegate 来完成的,
    从而得到bean 的定义信息,这些信息在Spring 中使用BeanDefinition 对象来表示-这个名字可以让我们想到loadBeanDefinition(),
    registerBeanDefinition()这些相关方法。它们都是为处理BeanDefinitin 服务的,容器解析得到BeanDefinition 以后,
    需要把它在IOC 容器中注册,这由IOC 实现BeanDefinitionRegistry 接口来实现。
    注册过程就是在IOC 容器内部维护的一个HashMap 来保存得到的BeanDefinition 的过程。这个HashMap 是IOC 容器持有Bean 信息的场所,
    以后对Bean 的操作都是围绕这个ConcurrentHashMap来实现的。然后我们就可以通过BeanFactory 和ApplicationContext 来享受到Spring IOC 的服务了,
    在使用IOC容器的时候,我们注意到除了少量粘合代码,绝大多数以正确IOC 风格编写的应用程序代码完全不用关心如何到达工厂,
    因为容器将把这些对象与容器管理的其他对象钩在一起。基本的策略是把工厂放到已知的地方,最好是放在对预期使用的上下文有意义的地方,
    以及代码将实际需要访问工厂的地方。Spring本身提供了对声明式载入web 应用程序用法的应用程序上下文,并将其存储在ServletContext 中的框架实现

时序图:
在这里插入图片描述

基于Annotation的IOC 初始化(https://www.cnblogs.com/wuzhenzhao/p/10863712.html)

  • 注解处理策略方式
    • 类注解 Spring 容器根据注解的过滤规则扫描读取注解Bean 定义类,并将其注册到Spring IOC 容器中 如@Component、@Repository、@Controller、@Service
    • 类内注解 通过Bean 后置注解处理器解析Bean 内部的注解 如 @Autowire、@Value、@Resource
  • 向容器注册方式(最终都是 向Bean添加到容器中一个管理BeanDefinition的HashMap中)
    • 容器创建后手动调用向容器注册,然后通过手动刷新容器,使得容器对注册的注解Bean 进行处理
    • 扫描指定包向容器注解

依赖注入(DI)(https://www.cnblogs.com/wuzhenzhao/p/10882050.html)

  • 用户第一次调用getBean()方法时,IOC 容器触发依赖注入
  • 当用户在配置文件中将元素配置了lazy-init=false 属性,即让容器在解析注册Bean 定义时进行预实例化,触发依赖注入
  • 过程
    • 缓存重置
    • 实例化
      • 使用简单工厂/工厂方法/容器的自动装配方法/参数匹配的构造方法/无参构造方法(反射(没有方法覆盖)/CGLib(有方法覆盖)) 生成Java 实例对象
    • 填充属性(依赖注入的过程就是Bean对象实例设置到它所依赖的Bean对象属性上去)
      • 属性值类型不需要强制转换时,不需要解析属性值,直接准备进行依赖注入

      • 属性值需要进行类型强制转换时,如对其他对象的引用(接口和实现类)等,首先需要解析属性值,然后对解析后的属性值进行依赖注入

      • 对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性

      • 对于非集合类型的属性,大量使用了JDK 的反射机制,通过属性的getter()方法获取指定属性注入以前的值,同时调用属性的setter()方法为属性设置注入后的值

    • 包装处理返回

Spring Bean

* bean作用域(prototype)
	* singleton 单例(默认值)
	* prototype 多例
	* request   每次HTTP请求都会创建一个新的Bean
	* session   同一个HTTP Session共享一个Bean
	* global-session  一般用于Portlet应用环境
	* 单例和多例选择
		* 单例 节省cpu和内存
		* 多例  防止有状态的实例并发线程安全问题
* 生命周期
	* Bean的定义——Bean的初始化——Bean的使用——Bean的销毁
* Bean 后置处理器
	(interface BeanPostProcessor)允许在调用初始化方法前后对 Bean 进行额外的处理
* Bean 定义继承

Spring 事件处理

* 单线程
* ApplicationContext加载 beans发布某些类型的事件(当上下文启动时,ContextStartedEvent 发布,当上下文停止时,ContextStoppedEvent 发布)
* ApplicationEvent ApplicationListener 提供在 ApplicationContext 中处理事件
* 如果一个 bean 实现 ApplicationListener,那么每次 ApplicationEvent 被发布到 ApplicationContext 上,那个 bean 会被通知
* 可以自定义事件

Spring AOP

* Aspect 一个模块具有一组提供横切需求的 APIs
* Join point 代表一个点
* Advice 这是实际行动之前或之后执行的
* Pointcut 一组一个或多个连接点
* 通知的类型
	* 前置 方法执行之前
	* 后置 方法执行之后(不考虑其结果)
	* 返回后 只有方法成功完成时
	* 抛出异常后 只有在方法退出抛出异常时
	* 环绕通知 调用之前和之后(手动写调用方法)

在这里插入图片描述在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐