• Spring中的设计模式


    1、简单工厂

    实现方式

    BeanFactory,Spring中的BeanFactory就是简单工厂模式的实现,根据传入一个唯一的标识来获得Bean对象。实质,由一个工厂类根据传入的参数,动态决定应该创建哪些产品类。

    实现原理
    Bean容器的启动阶段
    • 读取Bean的配置,将Bean元素分别转换成一个BeanDefinition对象。
    • 通过BeanDefinitionRegistry将这些Bean注册到BeanFactory中,保存在它的一个ConcurrentHashMap中。
    • 将BeanDefinition注册到了BeanFactory之后,在这里Spring为我们提供了一个扩展的切口,允许我们通过实现接口BeanFactoryPostProcessor在此处插入我们定义的代码。

    典型的例子就是PropertyPlaceHolderConfigurer,一般在配置数据库的dataSource时使用到的占位符的值,就是它注入进去的。

    容器中bean的实例化阶段

    CGLib (Code Generation Library) 是一个强大的、高性能、高质量的 Code 生成类库。它可以在运行期扩展 Java 类与实现 Java 接口。Hibernate 用它来实现 PO 字节码的动态生成。CGLib 比 Java 的 java.lang.reflect.Proxy 类更强的在于它不仅可以接管接口类的方法,还可以接管普通类的方法。

    JDK和CGLIB动态代理的区别

    • JDK动态代理只能针对接口实现类生成代理实例,而不能针对类,也就是面向接口的.
    • CGLIB是针对类实现代理,主要是对指定的类生成一个子类,并且覆盖其中方法实现增强,但是因为采用的是继承,所以该类或者方法最好不要声明为final.

    实例化阶段主要是通过反射或者CGLIB对bean进行实例化,在这个阶段Spring又暴露出很多的扩展点:

    • 各种的Aware接口,如BeanFactoryAware,对于实现了这些Aware接口的Bean,在实例化时Spring会帮我们注入对应的BeanFactory的实例。
    • BeanPostProcessor接口,实现了BeanPostProcessor接口的bean,在实例化时Spring会帮我们调用接口方法。
    • InitializingBean接口,实现了InitializingBean接口的Bean。
    设计意义
    松耦合

    可以将原来硬编码的依赖,通过Spring的BeanFactory这个工厂来注入依赖,也就是原来只有依赖方和被依赖方。现在引入了第三方——Spring的BeanFactory,由它来解决bean之间的依赖关系,达到了松耦合。

    bean的额外处理

    通过Spring暴露的接口,在实例化Bean的阶段,可以进行一些额外的处理,这些处理只需要让bean实现对应的接口即可,那么Spring就在在bean的生命周期调用我们实现的接口来处理改bean。

    Bean 的生命周期

    1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
    2. Bean实例化后对将Bean的引入和值注入到Bean的属性中
    3. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
    4. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
    5. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
    6. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
    7. 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,
    8. 如果bean使用init-method声明了初始化方法,该方法也会被调用如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
    9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
    10. 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

    2、工厂方法

    实现方式

    FactoryBean接口

    BeanFactory和FactoryBean的区别

    • BeanFactory是Bean的工厂,Spring的顶层核心接口,没有BeanFactory就没有Bean的存在。
    • FactoryBean也是一个接口,被他修饰的Bean将成为一个特殊的bean,原本的bean将被隐藏,而后由FactoryBean的getObject返回最终的bean,理解为FactoryBean是一个改装车行,它可以改装原本的Bean。
    实现原理

    实现了FactoryBean接口的bean是一类叫做factory的bean。其特点是,spring会在使用getBean()调用获得该bean时,会自动调用该bean的getObject()方法,所以返回的不是factory这个bean,而是这个bean.getOjbect()方法的返回值。

    代码示例(Spring和Mybatis的结合)

    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionFactory">
      
      <property name="dataSource" ref="dataSource">property>
      <property name="configLocation" value="classpath:mybatis-config-xml">property>
      <property name="mapperLocations" value="classpath:com/mapper/*.xml">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、单例模式

    Spring依赖注入Bean实例默认是单例的。Spring的依赖注入(包括Lazy-init方式)都是发生在AbstractBeanFactory的getBean里。getBean的doGetBean方法调用getSingleton进行bean的创建.spring依赖注入时,使用了 双重判断加锁 的单例模式.

    img

    **单例模式定义:**保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    Spring对单例模式的实现

    Spring中的单例模式,提供了全局访问点BeanFactory,但没有从构造器级别去控制单例,这是因为Spring管理的是任意的JAVA对象。

    4、装饰者模式

    指在不改变原有对象的基础上,将功能附加到对象上,比继承更加灵活。

    Spring中用到的包装器模式在类名上有两种表现,一种是类名中,含有Wrapper,另一种是含有Decorator。

    **适用场景:**动态地给一个对象添加一些额外的职责,就功能来说,Decorator模式相比生成子类更为灵活。

    **适用场景:**扩展一个类的功能或给一个类添加附加职责;动态给一个对象添加功能,这些功能可以再动态的撤销;在生活中,给煎饼加鸡蛋、蛋糕加水果、房子装修等都是在为对象扩展一些额外的职责。

    5、代理模式

    **辅助编程(AOP )是指面向切面编程:**通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

    Aop Spring 中的作用 提供声明式事务;允许用户自定义切面 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要 关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 … 切面( ASPECT ):横切关注点 被模块化 的特殊对象。即,它是一个类。 通知( Advice ):切面必须要完成的工作。即,它是类中的一个方法。 目标( Target ):被通知对象。 代理( Proxy ):向目标对象应用通知之后创建的对象。 切入点( PointCut ):切面通知 执行的 “ 地点 ” 的定义。 连接点( JointPoint ):与切入点匹配的执行点。

    AOP底层就是动态代理的实现。作用:动态代理作用:功能增强和控制访问

    既然动态代理是AOP实现,那么动态代理的角色必须与AOP相同。 也就是说,它主要用于方法的扩展。 这样,可以在不修改源代码的情况下扩展方法,并在方法执行前后做任何想做的事情。 因为InvocationHandler的invoke方法可以直接访问调用该方法的Method方法

    动态代理

    在内存构建中,不需要手动编写代理类

    静态代理

    需要手动编写代理类,代理类引用被代理对象。

    实现原理

    切面在应用运行的时刻被织入,一般情况下,在织入切面时,AOP容器会为目标对象动态的创建一个代理对象。

    织入:把切面应用到目标对象并创建新的代理对象的过程。

    6、观察者模式

    自定义需要发布的事件类,需要继承 ApplicationEvent 类或 PayloadApplicationEvent (该类也仅仅是对 ApplicationEvent 的一层封装)

    使用 @EventListener 来监听事件或者实现 ApplicationListener 接口。

    使用 ApplicationEventPublisher 来发布自定义事件(@Autowired注入即可)

    @TransactionalEventListener 监听器:如果事件的发布不是在事务(@Transactional)范围内,则监听不到该事件,除非将 fallbackExecution 标志设置为 true(@TransactionalEventListener(fallbackExecution = true));如果在事务中,可以选择在事务的哪个阶段来监听事件,默认在事务提交后监听(@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION))

    实现方式

    Spring的事件驱动模型使用的是观察者模式,Spring中Observer模式常用的地方是listener的实现。

    实现原理

    Spring中观察者模式的四个角色

    1.事件(ApplicationEvent)

    ApplicationEvent 是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过source得到事件源。

    下列描述了Spring提供的内置事件:

    • ContextRefreshedEvent:事件发布在 ApplicationContext 初始化或刷新时(例如:通过在 ConfigurableApplicationContext 接口使用refresh()方法)。这里,“初始化”意味着所有 bean 加载,post-processor bean 被检测到并且激活,单例预先实例化,ApplicationContext 对象可以使用了。只要上下文没有关闭,可以触发多次刷新, ApplicationContext 提供了一种可选择的支持这种“热”刷新。例如:XmlWebApplicationContext 支持热刷新,但 GenericApplicationContext 并非如此。具体是在 AbstractApplicationContext 的 finishRefresh() 方法中。
    • ContextStartedEvent:事件发布在 ApplicationContext 开始使用 ConfigurableApplicationContext 接口 start() 方法。这里,“开始”意味着所有生命周期 bean 接收到一个明确的起始信号。通常,这个信号用于明确停止后重新启动,但它也可以用于启动组件没有被配置为自动运行(例如:组件还没有开始初始化)。
    • ContextStoppedEvent:事件发布在 ApplicationContext 停止时通过使用 ConfigurableApplicationContext 接口上的 stop() 方法。在这里,“停止”意味着所有生命周期bean接收一个显式的停止信号。停止上下文可以通过重新调用start()方法。
    • ContextClosedEvent:事件发布在 ApplicationContext 关闭时通过关闭 ConfigurableApplicationContext 接口()方法。这里,“封闭”意味着所有单例 bean 被摧毁。一个封闭的环境达到生命的终结。它不能刷新或重启。
    • RequestHandledEvent:一个特定的web事件告诉所有能处理HTTP请求的bean 。这个事件是在请求完成后发布的。这个事件只适用于使用 Spring 的 DispatcherServlet 的web应用程序。

    2.事件监听(ApplicationListener)

    ApplicationListener 事件监听器,也就是观察者。继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent。当监听的事件发生后该方法会被执行。

    3.事件发布(ApplicationContext)

    ApplicationContext 是 Spring 中的核心容器,在事件监听中 ApplicationContext 可以作为事件的发布者,也就是事件源。因为 ApplicationContext 继承自 ApplicationEventPublisher。在 ApplicationEventPublisher 中定义了事件发布的方法 — publishEvent(Object event)

    4.事件管理(ApplicationEventMulticaster)

    ApplicationEventMulticaster 用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 Applicationcontext 发布的 Event 广播给它的监听器列表。

    事件机制的实现需要三部分(事件源、事件、事件监听器)

    ApplicationEvent抽象类【事件】:继承自JDK的EventObject,所有的事件都需要继承ApplicationEvent,并且通过构造器参数source得到事件源。该类的实现类ApplicationContextEvent表示ApplicationContext的容器事件。这个接口只有一个onApplicationEvent()方法。该方法接受一个ApplicationEvent或者其它子类对象作为参数,在方法体中,可以通过不同Event类的判断进行相应的处理。当事件触发时所有的监听器都会收到消息。

    public abstract class ApplicationEvent extends EventObject {
        /**
        * Constructs a prototypical Event.
        *
        * @param source The object on which the Event initially occurred.
        * @throws IllegalArgumentException if source is null.
        */
        public ApplicationEvent(Object source) {
            super(source);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ApplicationContext是spring中的全局容器,翻译过来是”应用上下文”。 实现了ApplicationEventPublisher接口。

    使用职责

    观察者模式:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并自动更新。此设计模式最重要的作用就是解耦!将观察者与被观察者解耦,使得他们之间的依赖性更小。

    7、策略模式

    比如说对象的某个行为,在不同场景中有不同的实现方式,这样就可以将这些实现方式定义为一组策略,每个实现类对应一个策略,在不同的场景就使用不同的实现类,从而实现自由切换策略。当程序中使用太多的if/else/switch来处理不同类型的业务时,会变得极难维护,通过策略模式可以更容易的实现业务扩展和维护。

    8、模板方法模式

    父类定义了骨架(调用哪些方法及顺序),某些特定方法由子类实现。最大的好处:代码复用,减少重复代码。除了子类要实现的特定方法, 其他方法及方法调用顺序都在父类中预先写好了。

    所以父类模板方法中有两类方法:

    **共同的方法:**所有子类都会用到的代码

    **不同的方法:**子类要覆盖的方法,分为两种:

    抽象方法:父类中的是抽象方法,子类必须覆盖

    钩子方法:父类中是一个空方法,子类继承了默认也是空的

    Spring模板方法模式实质:

    是模板方法模式和回调模式的结合,是Template Method不需要继承的另一种实现方式。Spring几乎所有的外接扩展都采用这种模式。

    9、责任链模式

    10、适配器模式

    spring和SpringMVC的联系和区别

    spring&springMVC 他两属于父子关系

    spring是粘合剂,是容器。它主要作用是粘合其他模块组件,进行统一管理

    Springmvc是spring扩展出的一个应用于Web端的框架

    spring框架核心

    IOC(控制反转):传统的过程中,当某个对象依赖于另外一个对象,会有该对象去创建另外一个对象,但是有了IOC之后,将创建过程交给IOC

    AOP(面向切面的编程)

    Spring MVC新特性

    提供了对Restful风格的支持

    @GetMapping,处理get请求

    @PostMapping,处理post请求

    @PutMapping,处理put请求

    @DeleteMapping,处理delete请求

    实现方式

    SpringMVC中的适配器HandlerAdatper

    实现原理

    HandlerAdatper根据Handler规则执行不同的Handler。

    实现过程

    DispatchServlet根据HandlerMapping返回的Handler,向Handler发起请求,处理Handler.

    HandleAdatper根据规则找到对应的Handler并让其执行,执行完毕后Handler会向HandlerAdaptper返回一个ModelAndView,最后由HandlerAdaptper想DispatchServlet返回一个ModelAndView。

    实现意义

    HandlerAdaptper是的Handler的扩展变得容易,只需要增加一个新的Handler和一个对应的HandlerAdaptper即可。所以Spring定义了一个适配接口,使得每一种Controller有一种对应的适配器实现类。让适配器代替controller执行相应的方法,这样在扩展Controller时,只需要增加一个适配器类就完成了SpringMVC的扩展。

    img

  • 相关阅读:
    金仓数据库 KingbaseES V8.3 至 V8.6 迁移最佳实践(4. V8.3 到 V8.6 数据库移植实战)
    浅谈模拟退火
    原创 | 一文读懂 BERT 源代码
    【快应用】如何通过计算属性控制组件样式
    苍穹外卖——项目搭建
    数据库之MVCC
    关于视频封装格式和视频编码格式的简介
    Python小知识点
    电脑重装系统后当前安全设置不允许下载该文件
    最新centos7 部署 k8s v1.26,简单易懂,跟着命令敲就完事
  • 原文地址:https://blog.csdn.net/qq_43545600/article/details/126682554