【转载】最全阿里 Java 面试题总结(开源框架知识)

目录

1.简单讲讲tomcat结构,以及其类加载器流程,线程模型等?

2.tomcat如何调优?涉及哪些参数?

3.讲讲Spring加载流程?

4.Spring AOP的实现原理?

5.讲讲Spring事务的传播属性?

6.Spring如何管理事务的?

7.Spring怎么配置事务(具体说出一些关键的xml 元素)?

8.说说你对Spring的理解,非单例注入的原理?它的生命周期?循环注入的原理,aop的实现原理,说说aop中的几个术语,它们是怎么相互工作的?

9.SpringMVC中DispatcherServlet初始化过程?

10.使用Spring框架的好处是什么? Spring由哪些模块组成?

11.springmvc用到的注解?作用是什么?原理?

12.springboot启动机制?

13.什么是Spring beans?

14.你怎样定义类的作用域?

15.如何给Spring容器提供配置元数据?

15.解释Spring支持的几种bean的作用域?

16.Spring框架中的单例bean是线程安全的吗?

17.解释Spring框架中bean的生命周期?

18.哪些是重要的bean生命周期方法? 你能重载它们吗?

19.什么是Spring的内部bean?

20.在Spring中如何注入一个java集合?

21.什么是bean装配?什么是bean的自动装配?解释不同方式的自动装配?

22.自动装配有哪些局限性?

23.你可以在Spring中注入一个null和一个空字符串吗?

24.什么是基于Java的Spring注解配置? 给一些注解的例子?

25.什么是基于注解的容器配置?

26.DispatcherServlet?

27.什么是Spring MVC框架的控制器?


1.简单讲讲tomcat结构,以及其类加载器流程,线程模型等?

Tomcat的核心组件就Connector和Container,一个Connector+一个Container(Engine)构成一个Service,Service就是对外提供服务的组件,有了Service组件Tomcat就能对外提供服务了,但是光有服务还不行,还需要有环境让你提供服务才行,所以最外层的Server就是为Service提供了生存的土壤。

Connector是一个连接器,主要负责接受请求并把请求交给Container,Container就是一个容器,主要装的是具有处理请求的组件。Service主要是为了关联Container与Connect,只有两个结合起来才能够处理一个请求。Server负责管理Service集合,从图中我们可以看到Tomcat可以提供多种服务,那么这些Service就是由Server来管理的。具体工作包括:对外提供一个接口访问Service,对内维护Service集合,维护Service集合包括管理Service声明周期等等。

<!-- Server代表整个容器,是Tomcat的顶层元素。服务器默认在8005端口,shutdown命令=关闭Tomcat -->
<Server>
    <Listener />
    <GlobaNamingResources>
    </GlobaNamingResources>
    <!-- Service包含多个Connector元素,而这些Connector元素共享一个Engine元素。 -->
    <Service>
    	<!-- Connector元素代表与客户时间交互的组件,它负责接收客户的请求,已经向客户响应结果,
    	配置http为https主要是修改Connector -->
        <Connector />
        <!-- 每个Service只能有一个Engine元素,处理同一个Service中所有Connector元素接收到的客户请求.
        Engine用来处理Connetcor收到的Http请求它匹配请求和自己的虚拟主机,并把请求转给对应的Host来处理 -->
        <Engine>
            <Logger />
            <Realm />
            	<!-- 一个Engine包含多个host元素,每个host元素定义了一个虚拟主机,它包含一个或多个Web应用 -->
                <host>
                    <Logger />
                    <!-- 由Context接口定义.是使用最频繁的元素,对应于一个Web App -->
                    <Context />
                </host>
        </Engine>
    </Service>
</Server>

类加载器流程:Tomcat启动时,会创建以下4种类加载器:

1.Bootstrap引导类加载器:加载JVM启动所需的类,以及标准扩展类(位于jar/lib/ext上)

2.System系统类加载器:加载Tomcat启动时的类,比如bootstrap.jar通常在catalina.bat或者catalina.sh中指定。指定位置位于CATALINA_HOME/bin下。

3.Common通用类加载器:加载tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,比如servlet-api.jar。

4.webapp应用类加载器:每个应用在创建后,都会创建一个唯一的类加载器。该类加载器会加载位于WEB-INF/lib下的jar文件中的class和WEB-INF/classes下的class文件。

红色虚线表示:应用需要到某个类时,则会按照下面的顺序进行类加载。
     ①、使用bootstrap引导类加载器加载
     ②、使用system系统类加载器加载
     ③、使用应用类加载器在WEB-INF/classes中加载
     ④、使用应用类加载器在WEB-INF/lib中加载
     ⑤、使用common类加载器在CATALINA_HOME/lib中加载

线程模型:支持以下四种线程模型:

2.tomcat如何调优?涉及哪些参数?

 Tomcat调优主要从四个方面考虑:

1.吞吐量;

2.Responsetime;

3.Cpuload;

4.MemoryUsage。

参数调优:

一、Tomcat启动参数的优化:

Tomcat 的启动参数位于tomcat的安装目录\bin目录下,如果你是Linux操作系统就是catalina.sh文件,如果你是Windows操作系统那么你需要改动的就是catalina.bat文件。

Linux系统中catalina.sh文件中添加如下参数(重要参数随后说明):

export JAVA_OPTS="-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking 
-XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC  -XX:+CMSParallelRemarkEnabled 
-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m  
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true "

Windowns系统中catalina.bat文件中添加如下参数(重要参数随后说明):

set JAVA_OPTS=-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking 
-XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31 
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC  -XX:+CMSParallelRemarkEnabled 
-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m  
-XX:+UseFastAccessorMethods 
-XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true

-Server(重要):只要Tomcat是运行在生产环境中,这个参数必须添加。因为Tomcat默认是java-client模式运行,添加server后表示以真实的production的模式运行,将拥有更大、更高的并发处理能力,更快、更强的JVM垃圾回收机制,可以获得更多的负载和吞吐量等等。

-Xms -Xmx:既JVM内存设置了,把Xms与Xmx两个值设成一样是最优的做法。(否则当内存=Xmx向Xms变化时,CPU高速运转触发垃圾回收机制,严重时会导致系统‘卡壳’,因此一开始我们就把这两个设成一样,使得Tomcat在启动时就为最大化参数充分利用系统的效率。)

PS:在设这个最大内存即Xmx值时请先打开一个命令行:能够正常显示JDK的版本信息,说明这个值能够用。

-Xmn:设置年轻代大小为512m。整个堆大小=年轻代 + 老年代 + 持久代。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

-Xss:是指设定每个线程的堆栈大小。这个就要依据程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等。一般不易设置超过1M,要不然容易出现out ofmemory。

二、Tomcat容器内优化:

打开tomcat安装目录\conf\server.xml文件。其中如下参数的默认值远远不够我们使用,我们对其进行了更改,更改后的配置如下:

<Connector port="8080" protocol="HTTP/1.1"           
URIEncoding="UTF-8"  minSpareThreads="25" maxSpareThreads="75"          
enableLookups="false" disableUploadTimeout="true" connectionTimeout="20000" 
acceptCount="300"  maxThreads="300" maxProcessors="1000" minProcessors="5"
useURIValidationHack="false"    
compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" 
redirectPort="8443" />

3.讲讲Spring加载流程?

ClassPathXmlApplicationContext实现beanFactory接口,是一个具体的实例化工厂。服务器启动时,解析xml配置文件,将对应文件中每个bean的id作为key,属性封装到beandefinition(是个对象)作为value,封装到一个ConCurrentHashMap容器A中。 同时,还有一个ConCurrentHashMap容器B存储bean的实例化对象,默认是空。当有一个请求时,首先去B中,查找。如果B容器没有,则访问A容器,如果是单例,则创建之后,仍要保存到B中,下次可以使用。如果是非单例的,则直接创建,并不在B中保存副本。

spring加载流程
1.监听器加载spring
2.加载配置文件
3.工厂生产实例化对象
4.放入ServletContext

4.Spring AOP的实现原理?

AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

实现AOP的技术,主要分为两大类:

一、采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;

二、采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

AOP使用场景:

Authentication 权限

Caching 缓存

Context passing  内容传递

Error handling  错误处理

Lazy loading 懒加载

Debugging 调试

logging, tracing, profiling and monitoring 记录跟踪 优化 校准

Performance optimization 性能优化

Persistence  持久化

Resource pooling 资源池

Synchronization 同步

Transactions 事务

如何使用Spring AOP:

可以通过配置文件或者编程的方式来使用Spring AOP。

配置可以通过xml文件来进行,大概有四种方式:

1. 配置ProxyFactoryBean,显式地设置advisors, advice, target等。

2. 配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从容器中获得的其实已经是代理对象。

3. 通过<aop:config>来配置。

4. 通过<aop: aspectj-autoproxy>来配置,使用AspectJ的注解来标识通知及切入点。

也可以直接使用ProxyFactory来以编程的方式使用Spring AOP,通过ProxyFactory提供的方法可以设置target对象, advisor等相关配置,最终通过 getProxy()方法来获取代理对象。

5.讲讲Spring事务的传播属性?

一、事务的定义
事务是指多个操作单元组成的合集,多个单元操作是整体不可分割的,要么都操作不成功,要么都成功。其必须遵循四个原则(ACID)。

1.原子性(Atomicity):即事务是不可分割的最小工作单元,事务内的操作要么全做,要么全不做。

2.一致性(Consistency):在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据还是应该处于正确的状态,即数据完整性约束没有被破坏;如银行转帐,A转帐给B,必须保证A的钱一定转给B,一定不会出现A的钱转了但B没收到,否则数据库的数据就处于不一致(不正确)的状态。

3.隔离性(Isolation):并发事务执行之间互不影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性。

4.持久性(Durability):事务一旦执行成功,它对数据库的数据的改变必须是永久的,不会因比如遇到系统故障或断电造成数据不一致或丢失。

据底层所使用的不同的持久化 API 或框架,使用如下:

1.DataSourceTransactionManager:适用于使用JDBC和iBatis进行数据持久化操作的情况,在定义时需要提供底层的数据源作为其属性,也就是 DataSource。

2.HibernateTransactionManager:适用于使用Hibernate进行数据持久化操作的情况,与 HibernateTransactionManager 对应的是 SessionFactory。

3.JpaTransactionManager:适用于使用JPA进行数据持久化操作的情况,与 JpaTransactionManager 对应的是 EntityManagerFactory。

二、事务的分类

数据库分为本地事务跟全局事务:

1.本地事务:普通事务,独立一个数据库,能保证在该数据库上操作的ACID。

2.分布式事务:涉及两个或多个数据库源的事务,即跨越多台同类或异类数据库的事务(由每台数据库的本地事务组成的),分布式事务旨在保证这些本地事务的所有操作的ACID,使事务可以跨越多台数据库。

Java事务类型分为JDBC事务跟JTA事务:

1.JDBC事务:即为上面说的数据库事务中的本地事务,通过connection对象控制管理。

2.JTA事务:JTA指Java事务API(Java Transaction API),是Java EE数据库事务规范,JTA只提供了事务管理接口,由应用程序服务器厂商(如WebSphere Application Server)提供实现,JTA事务比JDBC更强大,支持分布式事务。

按是否通过编程分为声明式事务和编程式事务:

1.声明式事务:通过XML配置或者注解实现。

2.编程式事务:通过编程代码在业务逻辑时需要时自行实现,粒度更小。

三、事务的基本原理

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:

  1. 获取连接 Connection con = DriverManager.getConnection()
  2. 开启事务con.setAutoCommit(true/false);
  3. 执行CRUD(CRUD是指在做计算处理时的增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写)
  4. 提交事务/回滚事务 con.commit() / con.rollback();
  5. 关闭连接 conn.close();

使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。
那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。下面简单地介绍下,注解方式为例子:

1.配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。

2.spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。

3.真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

四、Spring事务的传播属性

所谓spring事务的传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义,具体常量的解释见下表:

常量名称 常量解释
PROPAGATION_REQUIRED 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED

如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。

6.Spring如何管理事务的?

Spring事务管理主要包括3个接口,Spring的事务主要是由他们三个共同完成的。

1)PlatformTransactionManager:事务管理器--主要用于平台相关事务的管理

 主要有三个方法:

commit  事务提交;

rollback  事务回滚;

getTransaction  获取事务状态。

2)TransactionDefinition:事务定义信息--用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用

这个接口有下面四个主要方法:

getIsolationLevel:获取隔离级别;

getPropagationBehavior:获取传播行为;

getTimeout:获取超时时间;

isReadOnly:是否只读(保存、更新、删除时属性变为false--可读写,查询时为true--只读)。

事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。

3)TransactionStatus:事务具体运行状态--事务管理过程中,每个时间点事务的状态信息。

例如它的几个方法:

hasSavepoint():返回这个事务内部是否包含一个保存点;

isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚;

isNewTransaction():判断当前事务是否是一个新事务。

声明式事务的优缺点:

优点

不需要在业务逻辑代码中编写事务相关代码,只需要在配置文件配置或使用注解(@Transaction),这种方式没有侵入性。

缺点

声明式事务的最细粒度作用于方法上,如果像代码块也有事务需求,只能变通下,将代码块变为方法。

7.Spring怎么配置事务(具体说出一些关键的xml 元素)?

配置事务的方法有两种:

1)基于XML的事务配置;

2)基于注解方式的事务配置。

铺垫:

1)spring的事务管理是通过Aop的方式来实现;

2)声明式事务是spring对事务管理的最常用的方式,因为这种方式对代码的影响最小,因此也就符合非侵入式的轻量级的容器的概念。

<tx:advice id=“bankAdvice” transaction-manager=“transactionManager”>
<tx:attributes>
<tx:method name=“transfer” propagation=“REQUIRED”/>
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id=“bankPointcut” expression=“execution(* *.transfer(…))”/>
<aop:advisor advice-ref=“bankAdvice” pointcut-ref=“bankPointcut”/>
</aop:config>

8.说说你对Spring的理解,非单例注入的原理?它的生命周期?循环注入的原理,aop的实现原理,说说aop中的几个术语,它们是怎么相互工作的?

Spring的理解:

1)Spring是一个开源框架,主要是为简化企业级应用开发而生。可以实现EJB可以实现的功能,Spring是一个IOC和AOP容器框架。

控制反转(IOC):Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控制反转的思想。

依赖注入(DI):Spring使用Java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。

面向切面编程(AOP):在面向对象编程(OOP)思想中,我们将事物纵向抽象成一个个的对象。而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一些如权限验证,事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。

2)在Spring中,所有管理的都是JavaBean对象,而BeanFactory和ApplicationContext就是Spring框架的那个IOC容器,现在一般使用ApplicationContext,其不但包括了BeanFactory的作用,同时还进行了更多的扩展。

非单例注入原理:在大部分情况下,容器中的bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean或者一个非singleton bean要引用另外一个非singleton,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例。

9.SpringMVC中DispatcherServlet初始化过程?

//初始化多媒体解析器  

initMultipartResolver(context);  

//初始化位置解析器   

initLocaleResolver(context);

 //初始化主题解析器

initThemeResolver(context);  

//初始化HandlerMappings

initHandlerMappings(context);

//初始化HandlerAdapters

initHandlerAdapters(context);  

//初始化异常解析器  

initHandlerExceptionResolvers(context);

//初始化请求到视图名转换器  

initRequestToViewNameTranslator(context);  

//初始化视图解析器  

initViewResolvers(context);   

//初始化FlashMapManager   

initFlashMapManager(context);

在使用SpringMVC框架,会在web.xml文件配置一个DispatcherServlet,这正是web容器开始初始化,同时会在建立自己的上下文来持有SpringMVC的bean对象。

先从DispatcherServlet入手,从名字来看,它是一个Servlet。它的定义如下:

public class DispatcherServlet extends FrameworkServlet {

}

它是继承FrameworkServlet,来看一下整个的继承关系。

从继承关系来看,DispatcherServlet继承FrameworkServlet和HttpServletBean而继承HttpServlet,通过使用Servlet API来对HTTP请求进行响应,成为SpringMVC的前端处理器。

注:作为Servlet,DispatcherServlet的启动和Servlet的启动相关联的。在Servlet初始化过程中,Servlet的init方法会被调用,以进行初始化,然而DispatcherServlet的基类,所以从HttpServletBean中的初始化过程开始。

DispatcherServlet的工作分为2部分,一部分是初始化(也就是图的上半部分),有initServletBean()启动,通过initWebApplicationContext()方法最终调用DispatcherServlet中的initStrategies()方法。另一部分(也就是图的下半部分),是对HTTP请求进行响应,作为Servlet,Web容器会调用Servlet的doGet()和doPost()方法,在经过FrameworkServlet的processRequest()简单处理后,会调用DispatcherServlet的doService方法,在这个方法调用中封装了doDispatch(),继续调用processDispatchResult方法返回调用信息。

10.使用Spring框架的好处是什么? Spring由哪些模块组成?

轻量:Spring 是轻量的,基本的版本大约2MB。

控制反转(IOC):Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。

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

容器:Spring包含并管理应用中对象的生命周期和配置。

MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。

事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。

异常处理:Spring提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked异常。

Spring 框架的基本模块:

Core module

这是基本的Spring模块,提供spring框架的基础功能,BeanFactory是任何以spring为基础的应用的核心。Spring 框架建立在此模块之上,它使Spring成为一个容器。

Bean module

Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从正真的应用代码中分离。最常用的BeanFactory 实现是XmlBeanFactory 类。

XmlBeanFactory 最常用的就是org.springframework.beans.factory.xml.XmlBeanFactory ,它根据XML文件中的定义加载beans。该容器从XML 文件读取配置元数据并用它去创建一个完全配置的系统或应用

Context module

Expression Language module

JDBC module

Spring 通过提供ORM模块,支持我们在直接JDBC之上使用一个对象/关系映射映射(ORM)工具,Spring 支持集成主流的ORM框架,如Hiberate,JDO和 iBATIS SQL Maps。Spring的事务管理同样支持以上所有ORM框架及JDBC。

ORM module

OXM module

Java Messaging Service(JMS) module

Transaction module

Web module

Spring的WEB模块是构建在application context 模块基础之上,提供一个适合web应用的上下文。这个模块也包括支持多种面向web的任务,如透明地处理多个文件上传请求和程序级请求参数的绑定到你的业务对象。它也有对Jakarta Struts的支持。

Web-Servlet module

Web-Struts module

Web-Portlet module

11.SpringMVC用到的注解?作用是什么?原理?

SpringMVC核心原理

1、用户发送请求给服务器。url:user

2、服务器收到请求。发现Dispatchservlet可以处理。于是调用DispatchServlet。

3、DispatchServlet内部,通过HandleMapping检查这个url有没有对应的Controller。如果有,则调用Controller。

4、Control开始执行

5、Controller执行完毕后,如果返回字符串,则ViewResolver将字符串转化成相应的视图对象;如果返回ModelAndView对象,        该对象本身就包含了视图对象信息。

6、DispatchServlet将执视图对象中的数据,输出给服务器。

7、服务器将数据输出给客户端。

相关jar包含义

org.springframework.aop-3.0.3.RELEASE.jar         ----->  spring的aop面向切面编程

org.springframework.asm-3.0.3.RELEASE.jar      ----->  spring独立的asm字节码生成程序

org.springframework.beans-3.0.3.RELEASE.jar     ----->  IOC的基础实现

org.springframework.context-3.0.3.RELEASE.jar       ----->   IOC基础上的扩展服务

org.springframework.core-3.0.3.RELEASE.jar     ----->  spring的核心包

org.springframework.expression-3.0.3.RELEASE.jar    ----->  spring的表达式语言

org.springframework.web-3.0.3.RELEASE.jar     ------>  web工具包

org.springframework.web.servlet-3.0.3.RELEASE.jar   ------>  mvc工具包

在SpringMVC中,控制器Controller负责处理由DispatcherServlet分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model返回给对应的View进行展示。

在SpringMVC中提供了一个非常简便的定义Controller的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller标记一个类是Controller,然后使用@RequestMapping和@RequestParam等一些注解用以定义URL请求和Controller方法之间的映射,这样的Controller就能被外界访问到。此外Controller不会直接依赖于HttpServletRequest和HttpServletResponse等HttpServlet对象,它们可以通过Controller的方法参数灵活的获取到。

@Controller:

该注解表明该类扮演控制器的角色,Spring不需要你继承任何其他控制器基类或引用Servlet API。

@RequestMapping:

该注解是用来映射一个URL到一个类或一个特定的方处理法上。

12.springboot启动机制?

我们知道,如果不需要特殊的配置,只需要在main方法里调用SpringApplicatio.run()方法即可启动Spring Boot应用。

public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
}

SpringApplication启动流程:

第一步、初始化监听器

这里会初始化Spring Boot自带的监听器,以及添加到SpringApplication的自定义监听器。

第二步、发布ApplicationStartedEvent事件

到这一步,SpringBoot会发布一个ApplicationStartedEvent事件。如果你想在这个时候执行一些代码可以通过实现ApplicationListener接口实现。

第三步、装配参数和环境

在这一步,首先会初始化参数,然后装配环境,确定是web环境还是非web环境。

第四步、发布ApplicationEnvironmentPreparedEvent事件

准确的说,这个应该属于第三步,在装配完环境后,就触发ApplicationEnvironmentPreparedEvent事件。如果想在这个时候执行一些代码,可以订阅这个事件的监听器,方法同第二步。

第五步,打印Banner

看过Spring Boot实例教程 - 自定义Banner的同学会很熟悉,启动的Banner就是在这一步打印出来的。

第六步,创建ApplicationContext

这里会根据是否是web环境,来决定创建什么类型的ApplicationContext,ApplicationContext不要多说了吧,不知道ApplicationContext是啥的同学,出门左转补下Spring基础知识吧。

第七步,装配Context

这里会设置Context的环境变量、注册Initializers、beanNameGenerator等。

第八步,发布ApplicationPreparedEvent事件

这里放在第七步会更准确,因为这个是在装配Context的时候发布的。

值得注意的是:这里是假的,假的,假的,源码中是空的,并没有真正发布ApplicationPreparedEvent事件。不知道作者这么想的???

第九步,注册、加载等

注册springApplicationArguments、springBootBanner,加载资源等。

第十步,发布ApplicationPreparedEvent事件

注意,到这里才是真正发布了ApplicationPreparedEvent事件。这里和第八步好让人误解。

第十一步,refreshContext

装配context beanfactory等非常重要的核心组件。

第十二步,afterRefreshContext

这里会调用自定义的Runners,不知道Runners是什么的同学,请参考Spring Boot官方文档 - SpringApplication

第十三步,发布ApplicationReadyEvent事件

最后一步,发布ApplicationReadyEvent事件,启动完毕,表示服务已经可以开始正常提供服务了。通常我们这里会监听这个事件来打印一些监控性质的日志,表示应用正常启动了。添加方法同第二步。

注意:如果启动失败,这一步会发布ApplicationFailedEvent事件。

到这里,Spring Boot启动的一些关键动作就介绍完了。

13.什么是Spring beans?

Spring beans是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中<bean/> 的形式定义。

Spring 框架定义的beans都是单件beans。在bean tag中有个属性”singleton”,如果它被赋为true,bean就是单件,否则就是一个 prototype bean。默认是true,所以所有在Spring框架中的beans缺省都是单件。

14.你怎样定义类的作用域?

当定义一个<bean>在Spring里,我们还能给这个bean声明一个作用域。它可以通过bean定义中的scope属性来定义。如,当Spring要在需要的时候每次生产一个新的bean实例,bean的scope属性被指定为prototype。另一方面,一个bean每次使用的时候必须返回同一个实例,这个bean的scope 属性 必须设为 singleton。
 

15.如何给Spring容器提供配置元数据?

这里有三种重要的方法给Spring 容器提供配置元数据。

XML配置文件。

基于注解的配置。

基于Java的配置。

15.解释Spring支持的几种bean的作用域?

Spring框架支持以下五种bean的作用域:

singleton : bean在每个Spring ioc容器中只有一个实例。

prototype:一个bean的定义可以有多个实例。

request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。

session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

缺省的Spring bean 的作用域是Singleton。

16.Spring框架中的单例bean是线程安全的吗?

不,Spring框架中的单例bean不是线程安全的。

Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring bean并没有可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。

最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype”。

17.解释Spring框架中bean的生命周期?

Spring容器从XML文件中读取bean的定义,并实例化bean。

Spring根据bean的定义填充所有的属性。

如果bean实现了BeanNameAware接口,Spring传递bean的ID到setBeanName方法。

如果Bean实现了BeanFactoryAware接口, Spring传递beanfactory给setBeanFactory方法。

如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。

如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。

如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。

如果bean实现了DisposableBean,它将调用destroy()方法。

18.哪些是重要的bean生命周期方法? 你能重载它们吗?

有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown它是在容器卸载类的时候被调用。

The bean标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。

19.什么是Spring的内部bean?

当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,为了定义inner bean,在Spring 的基于XML的配置元数据中,可以在<property/>或<constructor-arg/>元素内使用<bean/>元素,内部bean通常是匿名的,它们的Scope一般是prototype。

20.在Spring中如何注入一个java集合?

Spring提供以下几种集合的配置元素:

<list>类型用于注入一列值,允许有相同的值。

<set>类型用于注入一组值,不允许有相同的值。

<map>类型用于注入一组键值对,键和值都可以为任意类型。

<props>类型用于注入一组键值对,键和值都只能为String类型。

package com.LHB.collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Department {
     private String name;
     private String[] empName;
     private List<Employee> empList;    //List集合
     private Set<Employee> empSets;     //Set集合
     private Map<String,Employee> empMap; //map集合
     private Properties pp;    //Properties的使用
}
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans
 6                 http://www.springframework.org/schema/beans/spring-beans.xsd
 7                 http://www.springframework.org/schema/context
 8                 http://www.springframework.org/schema/context/spring-context.xsd">
 9                 
10    <bean id="department" class="com.LHB.collection.Department">
11        <property name="name" value="财务部门" />
12        <!-- 给数组注入值 -->
13        <property name="empName">
14            <list>
15                <value>小米</value>
16                <value>小明</value>
17                <value>小四</value>
18            </list>
19        </property>
20        
21        <!-- 给list注入值 可以有相同的多个对象  -->
22        <property name="empList">
23            <list>
24                <ref bean="emp1" />
25                <ref bean="emp2"/>
26            </list>
27        </property>
28        <!-- 给set注入值 不能有相同的对象 -->
29        <property name="empSets">
30            <set>
31                <ref bean="emp1" />
32                <ref bean="emp2"/>
33            </set>
34        </property>
35        
36        <!-- 给map注入值 只要map中的key值不一样就可以装配value -->
37        <property name="empMap">
38            <map>
39                <entry key="1" value-ref="emp1" />
40                <entry key="2" value-ref="emp2" />
41            </map>
42        </property>
43        
44        <!-- 给属性集合配置 -->
45        <property name="pp">
46            <props>
47                <prop key="pp1">hello</prop>
48                <prop key="pp2">world</prop>
49            </props>
50        </property>
51    </bean>

21.什么是bean装配?什么是bean的自动装配?解释不同方式的自动装配?

装配,或bean装配是指在Spring容器中把bean组装到一起,前提是容器需要知道bean的依赖关系,如何通过依赖注入来把它们装配到一起。

Spring容器能够自动装配相互合作的bean,这意味着容器不需要<constructor-arg>和<property>配置,能通过Bean工厂自动处理bean之间的协作。

有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入:

no:默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。

byName:通过参数名自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。

byType:通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。

constructor:这个方式类似于byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。

autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。

22.自动装配有哪些局限性?

自动装配的局限性是:

重写:你仍需用 <constructor-arg>和 <property> 配置来定义依赖,意味着总要重写自动装配。

基本数据类型:你不能自动装配简单的属性,如基本数据类型,String字符串,和类。

模糊特性:自动装配不如显式装配精确,如果有可能,建议使用显式装配。

23.你可以在Spring中注入一个null和一个空字符串吗?

public class Boweifeng {

    private String email;

    public String getEmail() {

        return email;

    }

    public void setEmail(String email) {

        this.email = email;

    }

}

方式一注入:

<bean class="Boweifeng">

<property name="email"><value/></property>

</bean>

方式二注入:

<bean class="Boweifeng">

<property name="email" value=””/></property>

</bean>

方式三注入:

<bean class="Boweifeng">

<property name="email" value=”null”/></property>

</bean>

方式四注入:

<bean class="Boweifeng">

<property name="email" /><null/></property>

</bean>

方式一和二相当于执行了Java代码: Boweifeng.setEmail(""),设置的是空字符串。

方式三相当于执行了Java代码: Boweifeng.setEmail("null"),设置的是”null”字符串。

方式四的配置等同于Java代码:Boweifeng.setEmail(null)。<null/>用于处理null值。

24.什么是基于Java的Spring注解配置? 给一些注解的例子?

基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。

以@Configuration注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。另一个例子是@Bean注解,它

表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。

25.什么是基于注解的容器配置?

相对于XML文件,注解型的配置依赖于通过字节码元数据装配组件,而非尖括号的声明。

开发者通过在相应的类,方法或属性上使用注解的方式,直接对组件类中进行配置,而不是使用xml表述bean的装配关系。

26.DispatcherServlet?

Spring的MVC框架是围绕DispatcherServlet来设计的,它用来处理所有的HTTP请求和响应。

27.什么是Spring MVC框架的控制器?

控制器提供一个访问应用程序的行为,此行为通常通过服务接口实现。控制器解析用户输入并将其转换为一个由视图呈现给用户的模型。Spring用一个非常抽象的方式实现了一个控制层,允许用户创建多种用途的控制器。

猜你喜欢

转载自blog.csdn.net/Kevin_Gu6/article/details/88074705
今日推荐