首页 >> 大全

Spring MVC

2023-06-20 大全 50 作者:考证青年

Sping原理

是一个轻量级Java开发框架,最早有Rod 创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的/ full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。负责基础架构,因此Java开发者可以专注于应用程序的开发。

是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是它仍然可以和其他的框架无缝整合。

特点

轻量级: 组件大小与开销两方面而言都是轻量的。完整的框架可以在一个大小只有1M多的JAR文件中发布,并且所需的处理开销也是微不足道的。此外,是非侵入式,典型案例,应用中的对象不依赖于特定的类

控制反转: 通过控制反转(IOC)技术实现解耦。一个对象依赖的其他对象会通过被动的方式传递进来,而不需要对象自己创建或者查找依赖。

面向切面: 支持切面(AOP)编程,并且吧应用业务逻辑和系统服务区分开。

容器: 包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器。可以配置每个bean如何被创建、销毁,bean的作用范围是单例还是每次都生成一个新的实例,以及他们是如何相互关联。

框架集合: 将简单的组件配置,组合成为复杂的框架;应用对象被申明式组合;提供许多基础功能(事务管理、持久化框架继承),提供应用逻辑开发接口

框架优缺点 优点 缺点 框架中都用到了哪些设计模式

框架中使用到了大量的设计模式,下面列举了比较有代表性的:

核心组件

总共大约有 20 个模块, 由 1300 多个不同的文件构成。而这些组件被分别整合在核心容器(Core ) 、 AOP( )和设备支持() 、数据访问与集成(Data /) 、 Web、 消息() 、 Test等 6 个模块中。以下是 5 的模块结构图:

控制反转(IOC) 控制反转(IOC)概念

控制反转即IOC ( of ),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。

通过一个配置文件描述 Bean 及 Bean 之间的依赖关系,利用 Java 语言的反射功能(依赖注入DI)实例化 Bean 并建立 Bean 之间的依赖关系。 的 IoC 容器在完成这些底层工作的基础上,还提供 了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务。

容器高层视图

启动时读取应用程序提供的 Bean 配置信息,并在 容器中生成一份相应的 Bean 配

置注册表,然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,为上层应用提供准

备就绪的运行环境。其中 Bean 缓存池为 实现

IOC 容器实现 -框架基础设施

是 框架的基础设施,面向 本身;

面向使用 框架的开发者,几乎所有的应用场合我们都直接使用 而非底层的 。

面向开发应用

由 派生而来,提供了更多面向实际应用的功能。

继承了 ory 和 接口,在此基础

上,还通过多个其他的接口扩展了 的功能:

和 有什么区别?

和是的两大核心接口,都可以当做的容器。其中是的子接口。

依赖关系

:是里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。

:接口作为的派生,除了提供所具有的功能外,还提供了更完整的框架功能:

加载方式

:采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的的配置问题。如果Bean的某一个属性没有注入,加载后,直至第一次使用调用方法才会抛出异常。

:它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现中存在的配置错误,这样有利于检查所依赖属性是否注入。启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

相对于基本的, 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

创建方式

通常以编程的方式被创建,还能以声明的方式创建,如使用。

注册方式

和都支持、ssor的使用,但两者之间的区别是:需要手动注册,而则是自动注册。

通常的实现 的依赖注入

其主要实现方式有两种:依赖注入和依赖查找。

依赖注入: 相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入( ),即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。

依赖注入的基本原则

应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(中的)或者是构造器传递给需要的对象。

依赖注入优势

依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露的方法或者带参数的构造器或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:

依赖注入实现方式

依赖注入是时下最流行的IoC实现方式,依赖注入分为接口注入( ),方法注入( )和构造器注入( )三种方式。其中接口注入由于在灵活性和易用性比较差,现在从开始已被废弃。

构造器依赖注入和 方法注入的区别

两种依赖方式都可以使用,构造器注入和方法注入。最好的解决方案是用构造器参数实现强制依赖,方法实现可选依赖。

体系架构

t 是专门为 Web 应用准备的,它允许从相对于 Web 根目录的路径中装载配置文件完成初始化工作。从 t 中可以获得 的引用,整个 Web 应用上下文对象将作为属性放置到 中,以便 Web 应用环境可以访问 应用上下文。

Bean 定义

一个 Bean 的定义包含容器必知的所有配置元数据,包括如何创建一个bean,它的生命周期详情及它的依赖。

Bean 作用域

3 中为 Bean 定义了 5 中作用域,分别为 (单例)、(原型)、、 和 ,5 种作用域说明如下:

处理线程并发问题

在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在中,绝大部分Bean都可以声明为作用域,因为对一些Bean中非线程安全状态采用进行处理,解决线程安全问题。

和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而采用了“空间换时间”的方式。

会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进。

Bean 生命周期

实例化

实例化一个 Bean,也就是我们常说的 new。

IOC 依赖注入

按照 上下文对实例化的 Bean 进行配置,也就是 IOC 注入。

实现

如果这个 Bean 已经实现了 接口,会调用它实现的 ()方法,此处传递的就是 配置文件中 Bean 的 id 值

实现

如果这个 Bean 已经实现了 接口,会调用它实现的 ,

()传递的是 工厂自身(可以用这个方式来获取其它 Bean,只需在 配置文件中配置一个普通的 Bean 就可以)。

are 实现

如果这个 Bean 已经实现了 are 接口,会调用t()方法,传入 上下文(同样这个方式也可以实现步骤 4 的内容,但比 4 更好,因为 是 的子接口,有更多的实现方法)

接口实现-初始化预处理

如果这个 Bean 关联了 接口,将会调用( obj, s)方法, 经常被用作是 Bean 内容的更改,并且由于这个是在 Bean 初始化结束时调用那个的方法,也可以被应用于内存或缓存技术。

init-

如果 Bean 在 配置文件中配置了 init- 属性会自动调用其配置的初始化方法。

如果这个 Bean 关联了 接口,将会调用( obj, s)方法。

注:以上工作完成以后就可以应用这个 Bean 了,那这个 Bean 是一个 的,所以一般情况下我们调用同一个 id 的 Bean 会是在内容地址相同的实例,当然在 配置文件中也可以配置非 。

过期自动清理阶段

当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 这个接口,会调用那个其实现的 ()方法;

- 自配置清理

最后,如果这个 Bean 的 配置中配置了 - 属性,会自动调用其配置的销毁方法。

bean生命周期方法

bean 标签有两个重要的属性(init- 和 -)。用它们你可以自己定制

初始化和注销方法。它们也有相应的注解(@ 和@)。

什么是的内部bean?什么是 inner beans?

在框架中,当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean。

内部bean可以用注入“属性”和构造方法注入“构造参数”的方式来实现,内部bean通常是匿名的,它们的Scope一般是。

依赖注入四种方式构造器注入

/*带参数,方便利用构造器进行注入*/public CatDaoImpl(String message){this. message = message;}

方法注入

public class Id {private int id;public int getId() { return id; }public void setId(int id) { this.id = id; }}

  

静态工厂注入

静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让 管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过 注入的形式获取:

public class DaoFactory { //静态工厂public static final FactoryDao getStaticFactoryDaoImpl(){return new StaticFacotryDaoImpl();}}public class SpringAction {private FactoryDao staticFactoryDao; //注入对象//注入对象的 set 方法public void setStaticFactoryDao(FactoryDao staticFactoryDao) {this.staticFactoryDao = staticFactoryDao;}}

实例工厂

实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先 new 工厂类,再调用普通的实例方法:

public class DaoFactory { //实例工厂public FactoryDao getFactoryDaoImpl(){return new FactoryDaoImpl();}}public class SpringAction {private FactoryDao factoryDao; //注入对象public void setFactoryDao(FactoryDao factoryDao) {this.factoryDao = factoryDao;}}

5 种不同方式的自动装配

装配包括手动装配和自动装配,手动装配是有基于 xml 装配、构造方法、 方法等自动装配有五种自动装配的方式,可以用来指导 容器用自动装配方式来进行依赖注入。

中注入一个 Java

提供了以下四种集合类的配置元素:

      INDIA Pakistan USA UK      INDIA Pakistan USA UK               admin@nospam.com support@nospam.com    

使用@注解自动装配的过程

在使用@注解之前需要在配置文件进行配置,。

在启动 IoC时,容器自动装载了一个后置处理器,当容器扫描到@、@或@时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@时,首先在容器中查询对应类型的bean:

AOP AOP原理

OOP(- )面向对象编程,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。

AOP(- ),一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。

AOP 主要应用场景有

AOP 核心概念

引入():在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

中的代理

将 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。

+ = Proxy

AOP 实现方式

AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。

AOP 两种代理方式

提供了两种方式来生成代理对象: JDK Proxy 和 Cglib,具体使用哪种方式生成由 根据 对象的配置来决定。默认的策略是如果目标类是接口,则使用 JDK 动态代理技术,否则使用 Cglib 来生成代理。

JDK 动态接口代理

JDK 动态代理主要涉及到 java.lang. 包中的两个类:Proxy 和 。

是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。

Proxy 利用 动态创建一个符合某一接口的实例,生成目标类的代理对象。

CGLib 动态代理

CGLib 全称为 Code ,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了 asm,可以再运行期动态生成新的 class。和 JDK 动态代理相比较:JDK 创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。

实现原理

@Aspectpublic class TransactionDemo {@Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")public void point(){}@Before(value="point()")public void before(){System.out.println("transaction begin");}@AfterReturning(value = "point()")public void after(){System.out.println("transaction commit");}@Around("point()")public void around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("transaction begin");joinPoint.proceed();System.out.println("transaction commit");} }

在运行时通知对象

通过在代理类中包裹切面,在运行期把切面织入到管理的bean中。代理封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。当代理拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑。

直到应用需要被代理的bean时,才创建代理对象。如果使用的是的话,在从中加载所有bean的时候,才会创建被代理的对象。因为运行时才创建代理对象,所以我们不需要特殊的编译器来织入的切面。

只支持方法级别的连接点

因为基于动态代理,所以只支持方法连接点。缺少对字段连接点的支持,而且它不支持构造器连接点。方法之外的连接点拦截功能,我们可以利用来补充。

在 AOP 中,关注点和横切关注的区别是什么?在 aop 中 和 cross- 的不同之处

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了