出典:https://mp.weixin.qq.com/s/u3U1l3HvG6Dm6UJRB1epIA
この記事では、私たちが春の理解を深め、それはあまりにも多くのコードを伴わないであろう、いくつかの問題を通して考えています!かなり長い時間をコンパイルしたこの記事では、私はまた、使用の春の間に注意を払っていない多くの問題以下、それはまた、多くの情報に一時的にアクセスし、書籍が上に作ります。質問の春FAQ /表面仕上げに多くのオンラインの記事にもありますが、答えるためにいくつかの質問があり、私はすべてのほとんどはお互いをコピー感じるが、また、多くの問題は非常に良いではありません。だから私は少し仕上げ暇な時間の週を過ごし、私たちがお手伝いします。
春のフレームワークとは何ですか?
春はシステム開発者の開発効率と保守性の向上を目的とした軽量な開発フレームワークです。春の公式ウェブサイト:httpsを://spring.io/。
私たちは、一般的にSpringフレームワークは、多くのモジュールの集合である春のフレームワークへの参照であると言う、これらのモジュールを使用すると、簡単に私たちが開発を支援することができます。これらのモジュールは、次のとおりコアコンテナ、データアクセス/統合,,ウェブ、AOP(アスペクト指向プログラミング)、ツール、モジュールおよびテストメッセージ。例えば:コアコンテナコア成分は春、豆、およびコンポーネントは、ベースコンポーネントコンテキストIOC及び依存性注入である全ての成分のコアであり、AOPコンポーネントは指向プログラミングを実装するために使用されます。
公式サイトに記載されている春Springの6つの機能:
-
コア技術 :依存性注入(DI)、AOP、イベント(事象)、資源、国際化、検証、データバインディング、型変換、SPEL。
-
試験 :モックオブジェクト、TestContextフレームワーク、スプリングMVC試験、WebTestClient。
-
データアクセス :トランザクション、DAOのサポート、JDBC、ORMは、XMLをマーシャリングします。
-
Webサポート :Spring MVCのと春WebFluxのWebフレームワーク。
-
統合 :リモーティング、JMS、JCA、JMX、電子メール、タスク、スケジュール、キャッシング。
-
言語 :Kotlin、Groovyの、動的言語。
いくつかの重要な春のモジュールをリスト?
図Spring4.xは、対応するバージョンです。非同期応答プロセスのWebFluxコンポーネントを高めながら現在の最新バージョン5.xのWebモジュール内のポートレット・コンポーネントは、破棄されています。
春のメインモジュール
-
春のコア: ベース、他のすべての機能がライブラリのニーズに依存している春と言うことができます。IOCの依存性注入を提供する主な機能。
-
側面春は :モジュールはAspectJののサポートと統合されています。
-
AOP春は :アスペクト指向プログラミングを提供します。
-
JDBC春 :Javaデータベース接続。
-
JMS春 :Javaメッセージサービス。
-
ORM春 :Hibernateと他のORMツールのサポート。
-
ウェブ春 :Webアプリケーションを作成するためのサポートを提供します。
-
テスト春は :JUnitのとTestNGのテストのためのサポートを提供します。
春のIoCとAOPの理解についてのトーク
IoC
IoC(制御の逆:制御の反転)があるデザインのアイデアで 管理するために、Springフレームワークに渡し、もともとプログラムのマニュアルコントロールでオブジェクトを作成します。 他の言語のIOCはまた、アプリケーションが独自のSpirngていません。 スプリングIoCコンテナは、IoCのベクトルを達成するために使用され、実際にIoCコンテナマップ(キー、値)であり、マップは、様々なオブジェクトに格納されています。
IOCコンテナオブジェクト間の相互依存関係は、注入を完了するために、IOCのコンテナオブジェクトによって管理されます。これは、大幅にアプリケーション開発を簡素化することができ、アプリケーションが複雑な依存関係から解放されました。 IOCコンテナは、我々は、オブジェクトを作成する必要がある場合、あなただけの設定ファイル/注釈は、オブジェクトが外に作成されている方法を検討する必要になることはできません設定することができ、工場のようなものです。 実際のプロジェクトでは、サービスクラスは、可能性、我々はサービスをインスタンス化する必要がある場合、あなたはたびに、すべての基本となるクラスを、このサービスのコンストラクタを知りたいことがあり、その基になるように、クラスの数百あるいは数千を持っていること狂った人。IOCの使用した場合、あなただけの設定を行う必要があり、かつ、必要に応じて大幅にプロジェクトの保守性を向上させ、開発の労力を軽減行に引用されました。
春の時代、私たちは、一般的にSpringBootのコンフィギュレーションノートはゆっくりとポップアップ表示し始めたので、後に、非常に良い感じ設定するには、XMLファイルを開発したXMLファイルビーン、を使用して設定。
推奨読書ます。https://www.zhihu.com/question/23277575/answer/169698662
春IOCの初期化プロセス:
春IOCの初期化プロセス
IOCソース読みます
-
https://javadoop.com/post/spring-ioc
AOP
AOP(アスペクト指向プログラミング:指向プログラミング)にかかわらず、サービスのものとすることができる、しかし論理的または負債共同カプセル化と呼ばれるサービス・モジュール(例えば、トランザクション処理とは、管理、アクセス制御、等ログ)、容易にするために、コード複製低減システムを、モジュール間の結合を低減するため、および将来の拡張性と保守性を助長しています。
春AOPは、動的エージェントベースであるプロキシオブジェクトにしたい場合はインターフェイスを実装し、その後、春AOPを使用しますが、JDKプロキシのプロキシオブジェクトを作成するには、しかし、オブジェクトがインタフェースを実装していない、あなたがプロキシにJDKプロキシを使用することはできませんこの時間春AOPが使用CGLIBを 、春AOPが使用今回 CGLIBは、 以下に示すように、プロキシ・エージェントとしてオブジェクトのサブクラスを生成します。
SpringAOPProcess
もちろん、あなたはまた、AspectJのを使用することができ、春AOPはAspectJのと統合された、AspectJのは、Javaエコシステム上でカウントされなければならないAOPフレームワークの中で最も完全です。
AOPを使用した後、我々は抽象化、いくつかの一般的な機能を置くことができ、大幅に符号量を簡素化され、必要な場合、使用が直接使用することができます。我々はまた、システムのスケーラビリティを向上する新しい機能を追加する必要がある場合にも便利です。ロギング、トランザクション管理、およびので、現場にはAOPを使用しています。
春AOPとAspectJのAOPの違いは何ですか?
強化された春AOPを実行し、AspectJのは強化され、コンパイルされ属します。 AspectJのバイトコード操作(バイトコード操作)に基づいてスプリングAOPベースのエージェント(プロキシ)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。
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 的线程安全问题了解吗?
大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
常见的有两种解决办法:
-
在Bean对象中尽量避免定义可变的成员变量(不太现实)。
-
在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
Spring 中的 bean 生命周期?
这部分网上有很多文章都讲到了,下面的内容整理自:https://yemengying.com/2016/07/14/spring-bean-life-cycle/ ,除了这篇文章,再推荐一篇很不错的文章 :https://www.cnblogs.com/zrtqsk/p/3735273.html 。
-
Bean 容器找到配置文件中 Spring Bean 的定义。
-
Bean 容器利用 Java Reflection API 创建一个Bean的实例。
-
如果涉及到一些属性值 利用
set()
方法设置一些属性值。 -
如果 Bean 实现了
BeanNameAware
接口,调用setBeanName()
方法,传入Bean的名字。 -
如果 Bean 实现了
BeanClassLoaderAware
接口,调用setBeanClassLoader()
方法,传入ClassLoader
对象的实例。 -
如果Bean实现了
BeanFactoryAware
接口,调用setBeanClassLoader()
方法,传入ClassLoade
r对象的实例。 -
与上面的类似,如果实现了其他
*.Aware
接口,就调用相应的方法。 -
如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessBeforeInitialization()
方法 -
如果Bean实现了
InitializingBean
接口,执行afterPropertiesSet()
方法。 -
如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
-
如果有和加载这个 Bean的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessAfterInitialization()
方法 -
当要销毁 Bean 的时候,如果 Bean 实现了
DisposableBean
接口,执行destroy()
方法。 -
当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
图示:
Spring Bean 生命周期
与之比较类似的中文版本:
Spring Bean 生命周期
说说自己对于 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 , Spring MVC 使用更加简单和方便,开发效率更高,并且 Spring MVC 运行速度更快。
MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的Web层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)。
Spring MVC 的简单原理图如下:
SpringMVC 工作原理了解吗?
原理如下图所示:
SpringMVC运行原理
上图的一个笔误的小问题:Spring MVC 的入口函数也就是前端控制器 DispatcherServlet
的作用是接收请求,响应结果。
流程说明(重要):
-
客户端(浏览器)发送请求,直接请求到
DispatcherServlet
。 -
DispatcherServlet
根据请求信息调用HandlerMapping
,解析请求对应的Handler
。 -
解析到对应的
Handler
(也就是我们平常说的Controller
控制器)后,开始由HandlerAdapter
适配器处理。 -
HandlerAdapter
会根据Handler
来调用真正的处理器开处理请求,并处理相应的业务逻辑。 -
处理器处理完业务后,会返回一个
ModelAndView
对象,Model
是返回的数据对象,View
是个逻辑上的View
。 -
ViewResolver
会根据逻辑View
查找实际的View
。 -
DispaterServlet
把返回的Model
传给View
(视图渲染)。 -
把
View
返回给请求者(浏览器)
Spring 框架中用到了哪些设计模式?
关于下面一些设计模式的详细介绍,可以看笔主前段时间的原创文章《面试官:“谈谈Spring中都用到了那些设计模式?”。》 。
-
工厂设计模式 : Spring使用工厂模式通过
BeanFactory
、ApplicationContext
创建 bean 对象。 -
代理设计模式 : Spring AOP 功能的实现。
-
单例设计模式 : Spring 中的 Bean 默认都是单例的。
-
模板方法模式 : Spring 中
jdbcTemplate
、hibernateTemplate
等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。 -
包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
-
观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
-
适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配
Controller
。 -
……
@Component 和 @Bean 的区别是什么?
-
作用对象不同:
@Component
注解作用于类,而@Bean
注解作用于方法。 -
@Component
通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan
注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean
注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean
告诉了Spring这是某个类的示例,当我需要用它的时候还给我。 -
@Bean
注解比Component
注解的自定义性更强,而且很多地方我们只能通过@Bean
注解来注册bean。比如当我们引用第三方库中的类需要装配到Spring
容器时,则只能通过@Bean
来实现。
@Bean
注解使用示例:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
上面的代码相当于下面的 xml 配置
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
下面这个例子是通过 @Component
无法实现的。
@Bean
public OneService getService(status) {
case (status) {
when 1:
return new serviceImpl1();
when 2:
return new serviceImpl2();
when 3:
return new serviceImpl3();
}
}
将一个类声明为Spring的 bean 的注解有哪些?
我们一般使用 @Autowired
注解自动装配 bean,要想把类标识成可用于 @Autowired
注解自动装配的 bean 的类,采用以下注解可实现:
-
@Component
:通用的注解,可标注任意类为Spring
组件。如果一个Bean不知道属于拿个层,可以使用@Component
注解标注。 -
@Repository
: 对应持久层即 Dao 层,主要用于数据库相关操作。 -
@Service
: 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao层。 -
@Controller
: 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。
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。
参考
-
《Spring 技术内幕》
-
http://www.cnblogs.com/wmyskxz/p/8820371.html
-
https://www.journaldev.com/2696/spring-interview-questions-and-answers
-
https://www.edureka.co/blog/interview-questions/spring-interview-questions/
-
https://howtodoinjava.com/interview-questions/top-spring-interview-questions-with-answers/
-
http://www.tomaszezula.com/2014/02/09/spring-series-part-5-component-vs-bean/
-
https://stackoverflow.com/questions/34172888/difference-between-bean-and-autowired
(完)