龙空技术网

Spring知识点汇总

第一百零一招 225

前言:

如今同学们对“jsp加载完成事件”都比较关注,姐妹们都需要分析一些“jsp加载完成事件”的相关资讯。那么小编也在网络上汇集了一些对于“jsp加载完成事件””的相关文章,希望你们能喜欢,姐妹们一起来了解一下吧!

1.什么是Spring框架

Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。

我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:Core Container 中的 Core 组件是Spring 所有组件的核心,Beans 组件和 Context 组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。

Spring 官网列出的 Spring 的 6 个特征:

核心技术 :依赖注入(DI),AOP,事件(events),资源,i18n,验证,数据绑定,类型转换,SpEL。测试 :模拟对象,TestContext框架,Spring MVC 测试,WebTestClient。数据访问 :事务,DAO⽀持,JDBC,ORM,编组XML。Web⽀持 : Spring MVC和Spring WebFlux Web框架。集成 :远程处理,JMS,JCA,JMX,电⼦邮件,任务,调度,缓存。语⾔ :Kotlin,Groovy,动态语⾔。2.列举一些重要的Spring模块

下图对应的是 Spring4.x 版本。⽬前最新的5.x版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了⽤于异步响应式处理的 WebFlux 组件。

Spring Core:基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注⼊功能。Spring Aspects :该模块为与AspectJ的集成提供⽀持。Spring AOP :提供了⾯向切⾯的编程实现。Spring JDBC : Java数据库连接。Spring JMS :Java消息服务。Spring ORM : ⽤于⽀持Hibernate等ORM⼯具。Spring Web : 为创建Web应⽤程序提供⽀持。3.Spring IOC & AOP

谈谈你对Spring IOC和AOP的理解

IOC

IOC(Inverse of Control:控制反转)是⼀种设计思想,就是 将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语⾔中也有应⽤,并⾮ Spring 特有。 IOC 容器是 Spring⽤来实现 IOC 的载体, IOC容器实际上就是个Map(key,value),Map 中存放的是各种对象。

将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。IOC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。在实际项⽬中⼀个 Service 类可能有⼏百甚⾄上千个类作为它的底层,假如我们需要实例化这个Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把⼈逼疯。如果利⽤IOC的话,你只需要配置好,然后在需要的地⽅引⽤就⾏了,这大大增加了项⽬的可维护性且降低了开发难度。

Spring 时代我们⼀般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置不太好,于是SpringBoot 注解配置就慢慢开始流行起来。

自己语言组织是:以前创建对象的主动权和时机都是由自己把控的,IOC让对象的创建不用去new了,可以由spring自动生产,利用的是java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。

常见Spring IOC注入方式有三种:构造器注入、setter方法注入、根据注解注入。

Spring IOC的初始化过程:

AOP

AOP(Aspect-Oriented Programming:⾯向切⾯编程)能够将那些与业务⽆关,却为业务模块所共同调⽤的逻辑或责任(例如事务处理、⽇志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使⽤JDK Proxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候Spring AOP会使⽤Cglib ,这时候Spring AOP会使⽤ Cglib ⽣成⼀个被代理对象的⼦类来作为代理,如下图所示:

当然你也可以使⽤ AspectJ ,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java ⽣态系统中最完整的 AOP 框架了。

使⽤用AOP 之后我们可以把⼀些通用功能抽象出来,在需要⽤到的地⽅直接使⽤即可,这样⼤⼤简化了代码量。我们需要增加新功能时也方便,这样也提⾼了系统扩展性。⽇志功能、事务管理等等场景都⽤到了AOP。

Spring AOP里面的几个名词的概念关系图

一句话总结:IOC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。

4.Spring AOP 和 AspectJ AOP 有什么区别?

Spring AOP 属于运行时增强,⽽ AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而AspectJ 基于字节码操作(Bytecode Manipulation)。

Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java ⽣态系统中最完整的 AOP 框架了。

AspectJ 相比于 Spring AOP 功能更加强⼤,但是 Spring AOP 相对来说更简单,

如果我们的切⾯比较少,那么两者性能差异不⼤。但是,当切⾯太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。

5.Spring bean

Spring 中的 bean 的作⽤域有哪些?

singleton : 唯⼀ bean 实例,Spring 中的 bean 默认都是单例的。prototype : 每次请求都会创建⼀个新的 bean 实例。request : 每⼀次HTTP请求都会产⽣⼀个新的bean,该bean仅在当前HTTP request内有效。session : 每⼀次HTTP请求都会产⽣⼀个新的 bean,该bean仅在当前 HTTP session 内有效。global-session: 全局session作⽤域,仅仅在基于portlet的web应⽤中才有意义,Spring5已经没有了。Portlet是能够⽣成语义代码(例如:HTML)⽚段的⼩型Java Web插件。它们基于portlet容器,可以像servlet⼀样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话

Spring 中的单例 bean 的线程安全问题了解吗?

Spring容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体情况还是要结合Bean的作用域来讨论。

(1)对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。

(2)对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于方法本身。

释义:

有状态Bean(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。

无状态Bean(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。

常见的有两种解决办法:

在Bean对象中尽量避免定义可变的成员变量(不太现实)。在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的⼀种⽅式)。

释义:

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。

6.@Component 和 @Bean 的区别是什么?作⽤对象不同: @Component 注解作⽤于类,⽽ @Bean 注解作⽤于⽅法。@Component 通常是通过类路径扫描来⾃动侦测以及⾃动装配到Spring容器中(我们可以使⽤@ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类⾃动装配到 Spring 的bean 容器中)。 @Bean 注解通常是我们在标有该注解的⽅法中定义产⽣这个 bean, @Bean 告诉了Spring这是某个类的示例,当我需要⽤它的时候还给我。@Bean 注解⽐ Component 注解的⾃定义性更强,⽽且很多地⽅我们只能通过 @Bean 注解来注册bean。⽐如当我们引⽤第三⽅库中的类需要装配到 Spring 容器时,则只能通过 @Bean 来实现。

@Bean 注解使⽤示例:

@Configurationpublic class AppConfig { @Bean public TransferService transferService() { return new TransferServiceImpl(); }}

注:@Bean 需要在配置类中使用,即类上需要加上@Configuration注解

上⾯的代码相当于下⾯的 xml 配置

<beans> <bean id="transferService" class="com.acme.TransferServiceImpl"/></beans>

@Compent 注解使用示例

@Componentpublic class Student {    private String name = "lkm";    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

@Compent 作用是加在类上

下⾯这个例⼦是通过 @Component ⽆法实现的。

@Beanpublic OneService getService(status) { case (status) { when 1: return new serviceImpl1(); when 2: return new serviceImpl2(); when 3: return new serviceImpl3(); }}

自己语言组织:

@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。

@Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。通常方法体中包含了最终产生bean实例的逻辑。

@bean相对灵活可以独立加在方法上

将⼀个类声明为Spring的 bean 的注解有哪些?我们⼀般使⽤ @Autowired 注解⾃动装配 bean,要想把类标识成可⽤于 @Autowired 注解⾃动装配的 bean 的类,采⽤以下注解可实现:

@Component :通⽤的注解,可标注任意类为 Spring 组件。如果⼀个Bean不知道属于哪个层,可以使用 @Component 注解标注。@Repository : 对应持久层即 Dao 层,主要⽤于数据库相关操作。@Service : 对应服务层,主要涉及⼀些复杂的逻辑,需要⽤到 Dao层。@Controller : 对应 Spring MVC 控制层,主要⽤户接受⽤户请求并调⽤ Service 层返回数据给前端页面。7.Spring 中的 bean 生命周期?Bean 容器找到配置⽂件中 Spring Bean 的定义。Bean 容器利⽤ Java Reflection API 创建⼀个Bean的实例。如果涉及到⼀些属性值 利⽤ set() ⽅法设置⼀些属性值。如果 Bean 实现了 BeanNameAware 接⼝,调⽤ setBeanName() ⽅法,传⼊Bean的名字。如果 Bean 实现了 BeanClassLoaderAware 接⼝,调⽤ setBeanClassLoader() ⽅法,传⼊ClassLoader 对象的实例。与上⾯的类似,如果实现了其他 *.Aware 接⼝,就调⽤相应的⽅法。如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行 postProcessBeforeInitialization() ⽅法如果Bean实现了 InitializingBean 接⼝,执⾏行afterPropertiesSet() ⽅法。如果 Bean 在配置⽂件中的定义包含 init-method 属性,执⾏指定的⽅法。如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行 postProcessAfterInitialization() ⽅法当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接⼝,执⾏ destroy() ⽅法。当要销毁 Bean 的时候,如果 Bean 在配置⽂件中的定义包含 destroy-method 属性,执⾏指定的方法。

图示:

6.BeanFactory和ApplicationContext有什么区别?

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。

(1)BeanFactory是Spring里面最底层的接口,是IoC的核心,定义了IoC的基本功能,包含了各种Bean的定义、加载、实例化,依赖注入和生命周期管理。ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:

继承MessageSource,因此支持国际化。资源文件访问,如URL和文件(ResourceLoader)。载入多个(有继承关系)上下文(即同时加载多个配置文件) ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。提供在监听器中注册bean的事件。

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

②ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。

③ApplicationContext启动后预载入所有的单实例Bean,所以在运行的时候速度比较快,因为它们已经创建好了。相对于BeanFactory,ApplicationContext 唯一的不足是占用内存空间,当应用程序配置Bean较多时,程序启动较慢。

(3)BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

(4)BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

7.Spring MVC

说说⾃⼰对于 Spring MVC 了解?

谈到这个问题,我们不得不提提之前 Model1 和 Model2 这两个没有 Spring MVC 的时代。

Model1 时代 : 很多学 Java 后端⽐᫾晚的朋友可能并没有接触过 Model1 模式下的 JavaWeb应⽤开发。在 Model1 模式下,整个 Web 应⽤⼏乎全部⽤ JSP ⻚⾯组成,只⽤少量的JavaBean 来处理数据库连接、访问等操作。这个模式下 JSP 即是控制层⼜是表现层。显⽽易⻅,这种模式存在很多问题。⽐如①将控制逻辑和表现逻辑混杂在⼀起,导致代码重⽤率极低;②前端和后端相互依赖,难以进⾏测试并且开发效率极低;Model2 时代 :学过 Servlet 并做过相关 Demo 的朋友应该了解“Java Bean(Model)+JSP(View,)+Servlet(Controller) ”这种开发模式,这就是早期的 JavaWeb MVC 开发模式。Model:系统涉及的数据,也就是 dao 和 bean。View:展示模型中的数据,只是⽤来展示。Controller:处理⽤户请求都发送给 ,返回数据给 JSP 并展示给⽤户。

Model2 模式下还存在很多问题,Model2的抽象和封装程度还远远不够,使⽤Model2进⾏开发时不可避免地会重复造轮⼦,这就⼤⼤降低了程序的可维护性和复⽤性。于是很多JavaWeb开发相关的 MVC 框架应运⽽⽣⽐如Struts2,但是 Struts2 ⽐᫾笨重。随着 Spring 轻量级开发框架的流⾏,Spring ⽣态圈出现了 Spring MVC 框架, Spring MVC 是当前最优秀的 MVC 框架。相⽐于 Struts2 , SpringMVC 使⽤更加简单和⽅便,开发效率更⾼,并且 Spring MVC 运⾏速度更快。

MVC 是⼀种设计模式,Spring MVC 是⼀款很优秀的 MVC 框架。Spring MVC 可以帮助我们进⾏更简洁的Web层的开发,并且它天⽣与 Spring 框架集成。Spring MVC 下我们⼀般把后端项⽬分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)。

Spring MVC 的简单原理图如下:

SpringMVC 工作原理了解吗?

原理图示:

上图的⼀个笔误的⼩问题:Spring MVC 的⼊⼝函数也就是前端控制器 DispatcherServlet 的作⽤是接收请求,响应结果。

流程说明(重要):

客户端(浏览器)发送请求,直接请求到 DispatcherServlet 。2. DispatcherServlet 根据请求信息调⽤ HandlerMapping ,解析请求对应的 Handler 。解析到对应的 Handler (也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。HandlerAdapter 会根据 Handler 来调⽤真正的处理器开处理请求,并处理相应的业务逻辑。处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象, View 是个逻辑上的 View 。ViewResolver 会根据逻辑 View 查找实际的 View 。DispaterServlet 把返回的 Model 传给 View (视图渲染)。把 View 返回给请求者(浏览器)8.Spring 框架中⽤到了哪些设计模式?

列举常见:

⼯⼚设计模式 : Spring使⽤⼯⼚模式通过 BeanFactory 、 ApplicationContext 创建 bean 对象。代理设计模式 : Spring AOP 功能的实现。单例设计模式 : Spring 中的 Bean 默认都是单例的。包装器设计模式 : 我们的项⽬需要连接多个数据库,⽽且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。观察者模式: Spring 事件驱动模型就是观察者模式很经典的⼀个应⽤。适配器模式 :Spring AOP 的增强或通知(Advice)使⽤到了适配器模式、spring MVC 中也是⽤到了适配器模式适配 Controller 。......9.Spring 事务

Spring 管理事务的⽅式有⼏种?

编程式事务,在代码中硬编码。(不推荐使⽤)声明式事务,在配置⽂件中配置(推荐使⽤)

声明式事务又分为两种:

基于XML的声明式事务基于注解的声明式事务

Spring 事务中的隔离级别有哪⼏种?

TransactionDefinition 接⼝中定义了五个表示隔离级别的常量:

TransactionDefinition.ISOLATION_DEFAULT: 使⽤后端数据库默认的隔离级别,Mysql 默认采⽤的 REPEATABLE_READ隔离级别 Oracle 默认采⽤的 READ_COMMITTED隔离级别.TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修改,可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。TransactionDefinition.ISOLATION_SERIALIZABLE: 最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说,该级别可以防⽌脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会⽤到该级别。

Spring 事务中哪几种事务传播行为?

⽀持当前事务的情况:

TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

不支持持当前事务的情况:

TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_NEVER: 以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。

其他情况:

TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

@Transactional(rollbackFor = Exception.class)注解了解吗?

我们知道:Exception分为运⾏时异常RuntimeException和⾮运⾏时异常。事务管理对于企业应⽤来说是⾄关重要的,即使出现异常情况,它也可以保证数据的⼀致性。

当 @Transactional 注解作⽤于类上时,该类的所有 public ⽅法将都具有该类型的事务属性,同时,我们也可以在⽅法级别使⽤该标注来覆盖类级别的定义。如果类或者⽅法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

在 @Transactional 注解中如果不配置 rollbackFor 属性,那么事物只会在遇到 RuntimeException 的时候才会回滚,加上 rollbackFor=Exception.class ,可以让事物在遇到⾮运⾏时异常时也回滚。

9.JPA

JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

如何使⽤JPA在数据库中⾮持久化⼀个字段?

示例:

Entity(name="USER")public class User {  @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") private Long id; @Column(name="USER_NAME") private String userName; @Column(name="PASSWORD") private String password;     private String secrect; } 

如果我们想让 secrect 这个字段不被持久化,也就是不被数据库存储怎么办?我们可以采⽤下⾯⼏种

⽅法:

static String transient1; // not persistent because of staticfinal String transient2 = “Satish”; // not persistent because of finaltransient String transient3; // not persistent because of transient@TransientString transient4; // not persistent because of @Transient

⼀般使⽤后⾯两种⽅式比较多,我个⼈使⽤注解的⽅式比较多。注:

@Transient:指定的属性,它是不持久的,即:该值永远不会存储在数据库中。

JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个

标签: #jsp加载完成事件