• Spring 框架的设计理念与设计模式


    Spring 框架的设计理念与设计模式

    Spring核心学习点

    • IoC容器:Spring核心是IoC容器,所以一定要透彻理解什么是IoC容器,以及如何配置及使用容器,其他所有技术都是基于容器实现的;
    • 面向切面编程:首先还是明确概念,基本配置,最后是实现原理,接下来就是数据库事务管理,其实Spring管理事务是通过面向切面编程实现的

    一、Spring核心容器组件

    Spring 的三大组件 :Bean 、 Context、Core
    spring

    Bean(一场演出中的演员):

    提供了框架的基础部分,包括反转控制和依赖注入。其中Bean Factory是容器核心,本质是“工厂设计模式”的实现,而且无需编程实现“单例设计模式”,单例完全由容器控制,而且提倡面向接口编程,而非面向实现编程;所有应用程序对象及对象间关系由框架管理,从而真正把你从程序逻辑中把维护对象之间的依赖关系提取出来,所有这些依赖关系都由BeanFactory来维护

    Context(演出的舞台背景):

    以Core和Beans为基础,集成Beans模块功能并添加资源绑定、数据验证、国际化、Java EE支持、容器生命周期、事件传播等;核心接口是ApplicationContext,
    ApplicationContext将完成:

    • (1)标识一个应用环境
    • (2)利用BeanFactory创建Bean对象
    • (3)保存对象关系表
    • (4)能够捕获各种事件

    Core(演出的道具):

    封装了框架依赖的最底层部分,包括资源访问、类型转换及一些常用工具类

    二、Spring核心理念:

    • 面向Bean编程:将对象间的依赖关系用配置文件管理,在一个叫做IOC容器中管理,这个容器里就是被Bean包裹的对象

    1.IoC容器工作原理

    IoC容器实际上是Context组件结合另外其他两个组件共同构建了一个Bean的关系网。

    (1)初始化

    初始化的过程主要就是读取XML资源,并解析,最终注册到Bean Factory中
    初始化的流程:
    init

    然后会刷新,将该新加入的Bean放入整个关系网中去:刷新的入口就在AbstractApplicationContextrefresh方法里:

    public void refresh() throws BeansException, IllegalStateException {
            Object var1 = this.startupShutdownMonitor;
            synchronized(this.startupShutdownMonitor) {
                //为刷新准备新的Context
                this.prepareRefresh();
                //刷新所有BeanFactory子容器 
                ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();  //创建BeanFactory
                this.prepareBeanFactory(beanFactory);  //添加一些工具类
    
                try {
                    //
                    this.postProcessBeanFactory(beanFactory);
                    //
                    this.invokeBeanFactoryPostProcessors(beanFactory);
                    //
                    this.registerBeanPostProcessors(beanFactory);
                    this.initMessageSource();
                    this.initApplicationEventMulticaster();
                    this.onRefresh();
                    this.registerListeners();
                    this.finishBeanFactoryInitialization(beanFactory);
                    this.finishRefresh();
                } catch (BeansException var9) {
                    if (this.logger.isWarnEnabled()) {
                        this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                    }
    
                    this.destroyBeans();
                    this.cancelRefresh(var9);
                    throw var9;
                } finally {
                    this.resetCommonCaches();
                }
    
            }
        }
    

    这个方法就是构建IoC容器的整个流程,非常重要,主要包含着几个步骤:

    (1)构建BeanFactory,以便生产所需的“演员”
    (2)注册可能感兴趣的事件
    (3)创建Bean 实例对象
    (4)触发被监听的事件

    首先this.obtainFreshBeanFactory(); //创建BeanFactory中会执行解析和注册bean的过程,通过parseBeanDefinitionElement将XML的元素解析为BeanDefinition,然后存在BeanDefinitionHolder中,然后再利用BeanDefinitionHolder将BeanDefinition注册,实质就是把BeanDefinition的实例put进BeanFactory中.
    注册过程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition),也就是说注册的实质就是以beanName为key,以beanDefinition为value,将其put到HashMap中。

    其中,这三行代码对Spring 的功能扩展起到了关键作用:

    this.postProcessBeanFactory(beanFactory); // -> 注册实现了BeanPostProcessor接口的Bean
    
    this.invokeBeanFactoryPostProcessors(beanFactory);// ->初始化和执行BeanFactoryPostProcessors beans
    
    this.registerBeanPostProcessors(beanFactory);  // -> 初始化和执行BeanPostProcessors beans
    

    invokeBeanFactoryPostProcessors方法主要是获取实现BeanFactoryPostProcessors接口的子类,并且执行它的postProcessBeanFactory方法.

    这两个接口的作用:
    BeanFactoryPostProcessor和BeanPostProcessor,这两个接口,都是Spring初始化bean时对外暴露的扩展点。

    • BeanFactoryPostProcessor接口实现类可以在当前BeanFactory初始化后,bean实例化之前对BeanFactory做一些处理。BeanFactoryPostProcessor是针对于bean容器的,在调用它时,BeanFactory只加载了bean的定义,还没有对它们进行实例化,所以我们可以通过对BeanFactory的处理来达到影响之后实例化bean的效果。
    • BeanPostProcessor 接口定义了一个你可以自己实现的回调方法,来实现你自己的实例化逻辑、依赖解决逻辑等,如果你想要在Spring完成对象实例化、配置、初始化之后实现自己的业务逻辑,你可以补充实现一个或多个BeanPostProcessor的实现。

    如下图所示:Spring Bean的生命周期:
    post

    (2)依赖注入

    当完成初始化IOC容器后,如果bean没有设置lazy-init(延迟加载)属性,那么bean的实例就会在初始化IOC完成之后,及时地进行初始化。初始化时会先建立实例,然后根据配置利用反射对实例进行进一步操作,具体流程如下所示:

    fac

    AbstractAutowireCapableBeanFactory类中,进行创建bean和注入bean的属性

    2.Spring AOP原理

    Spring中的 AOP就是基于动态代理实现的。

    AOP技术利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
    使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

    在AOP之前,先了解下ApectJ :

    ApectJ 是什么

    AspectJ是一套独立的面向切面编程的解决方案。

    Spring采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这是与AspectJ(静态织入)最根本的区别。

    AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:

    1、定义普通业务组件
    2、定义切入点,一个切入点可能横切多个业务组件
    3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作

    三、Spring中的设计模式

    Spring 中的单例模式

    Spring 中的代理模式

    Java中的代理主要分为3种:

    • 静态代理
    • 动态代理
    • Cglib代理
      Spring 中的AOP 是代理模式的应用。

    代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问;
    使用代理模式创建代理对象,让代理对象控制某对象的访问,被代理的对象可以是远程对象,创建开销大
    的对象或需要安全控制的对象

    动态代理的实现:JDK中生成代理对象的API
    代理类所在包:java.lang.reflect.Proxy
    JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是:

    static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
    
    

    Spring 中的工厂模式

    Spring中在各种BeanFactory以及ApplicationContext创建中都用到了典型的工厂方法模式,BeanFactory的设计原理如图所示。

    bean

    来看看其中BeanFactory源码:

    public interface BeanFactory {
        String FACTORY_BEAN_PREFIX = "&";
    
        Object getBean(String var1) throws BeansException;
    
        <T> T getBean(String var1, Class<T> var2) throws BeansException;
    
        <T> T getBean(Class<T> var1) throws BeansException;
    
        Object getBean(String var1, Object... var2) throws BeansException;
    
        <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    
        boolean containsBean(String var1);
    
        boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    
        boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    
        Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    
        String[] getAliases(String var1);
    }
    

    Bean包里主要包括Bean的定义、创建和解析,也就是配置xml文件,被解析后就被转化为Bean,由Spring统一管理.

    Spring 中的模版方法

  • 相关阅读:
    oracle热备份与冷备份的对比
    oracle数据库备份
    shell 去除空行
    已有实例 Oracle 下新增实例(2)通过dbca克隆实例
    oracle启动,提示“LRM-00109: could not open parameter file”
    linux——使用fidsk对linux硬盘进行操作【转】
    前端——知识点
    hdu 3996 Gold Mine 最大权闭合子图
    hdu 3917 Road constructions 最大权闭合子图
    poj 2987 Firing 最大权闭合子图
  • 原文地址:https://www.cnblogs.com/shawshawwan/p/10104415.html
Copyright © 2020-2023  润新知