什么是Spring 框架?Spring 框架有哪些次要模块?
Spring框架是一个为Java利用程序开发提供了综合、宽泛的基础性反对的平台。Spring集成了Java开发过程中所需的各种组件、库和依赖包,使得开发人员能够专一于利用的开发,而不必在各种底层组件依赖上破费大量工夫,并且这些工夫在每个我的项目上是反复节约的。
Spring 框架曾经集成了20 多个模块。这些模块次要蕴含外围容器(spring-core/spring-beans)、数据拜访/集成、Web(spring-web)、AOP(spring-aop/spring-aspects)、工具、音讯和测试模块。
另外这里集体整顿了一些材料,有须要的敌人能够间接点击支付。
Java基础知识合集
百本Java架构师外围书籍
对标阿里P7的java架构师学习路线图
联合金三银四整顿的2021年最新面试题
应用Spring 框架能带来哪些益处?
Spring 框架带来的次要益处:
- 与EJB容器相比拟,IOC 容器更加趋向于轻量级,使得IOC 容器能够在无限的内存和CPU 资源的状况下进行应用程序的开发和公布。
- DI机制升高了业务对象替换的复杂性,进步了组件之间的解耦。
- Spring的AOP反对容许将一些通用工作如平安、事务、日志等进行集中式治理,从而提供了更好的复用。
- 除了本身已有的技术外(比方ORM 框架、logging 框架、J2EE、Quartz和JDK Timer),Spring还集成了很多其余根底技术,比方JDBC、Transaction等。
- Spring 框架是依照模块的模式来组织的。由包和类的编号就能够看出其所属的模块,Spring并不强制利用齐全依赖于Spring,开发者可自在选用Spring框架的局部或全副。
- Spring的ORM和DAO提供了与第三方长久层框架的良好整合,并简化了底层的数据库拜访。
什么是IOC?什么是DI?
- IOC(Inversion of Control)叫管制反转, DI(Dependency Injection)叫依赖注入,是对IOC更简略的诠释。
- IOC 管制反转是把传统上由程序代码间接操控的对象的调用权交给容器,通过容器来实现对象组件的拆卸和治理。所谓的"管制反转"就是对组件对象控制权的转移,从程序代码自身转移到了内部容器,由容器来创建对象并治理对象之间的依赖关系。
- DI 依赖注入的根本准则是利用组件不应该负责查找资源或者其余依赖的合作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从利用组件的代码中抽取进去,交给容器来实现。DI是对IOC更精确的形容,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动静的将某种依赖关系注入到组件之中。
在Java中依赖注入有哪些形式?
- 接口注入:指的就是在接口中定义要注入的信息,并通过接口实现注入。
- set注入:指的就是在承受注入的类中定义一个set办法,并在参数中定义须要注入的元素。
- 结构器注入:指的就是承受注入的类中定义一个构造方法,并在参数中定义须要注入的元素。
@Component("visitor") public class VisitTeacher { // 接口注入 @Autowired private Teacher teacher; // 结构器注入 @Autowired public VisitTeacher(Teacher teacher) { this.teacher = teacher; } // Setter注入 @Autowired public void setTeacher(Teacher teacher) { this.teacher = teacher; } public void say() { teacher.say(); } }
- 设值注入:先通过无参数的构造函数创立一个Bean实例,而后调用对应的setter办法注入依赖关系(设置注入就是指要被注入的类中定义有一个setter()办法,并在参数中定义须要注入的对象。)
- 结构注入:间接调用有参数的结构器,当bean实例创立实现后,曾经实现了依赖关系的注入(结构注入就是指要被注入的类中申明一个构造方法,并在此办法的参数中定义要注入的对象。)
BeanFactory 和ApplicationContext 有什么区别?
BeanFactory 能够了解为含有bean 汇合的工厂类。BeanFactory 蕴含了种bean 的定义,以便在接管到客户端申请时将对应的bean 实例化。BeanFactory 还能在实例化对象时生成合作类之间的关系。BeanFactory 还蕴含了bean 生命周期的管制,调用客户端的初始化办法(initialization Methods)和销毁办法(destruction Methods)。
从外表上看,ApplicationContext 如同bean factory 一样具备bean 定义、bean 关联关系的设置,依据申请散发bean的性能。但ApplicationContext在此基础上还提供了其余的性能。
- 提供了反对国际化的文本音讯
- 对立的资源文件读取形式
- 已在监听器中注册的bean 的事件
以下是三种较常见的ApplicationContext 实现形式:
- ClassPathXmlApplicationContext:从classpath 的XML 配置文件中读取上下文,并生成上下文定义。应用程序上下文从程序环境变量中获得。
ApplicationContext context = new ClassPathXmlApplicationContext(“application.xml”);
- FileSystemXmlApplicationContext :由文件系统中的XML 配置文件读取上下文。
ApplicationContext context = new FileSystemXmlApplicationContext(“application.xml”);
- XmlWebApplicationContext:由Web 利用的XML 文件读取上下文。
Spring 提供几种配置形式来设置元数据?
将Spring 配置到利用开发中有以下三种形式:
- 基于XML 的配置
- 基于注解的配置
- 基于Java 的配置
前两种比较简单,次要介绍基于Java Config的配置化。Spring3.0提供了一些注解反对通过java类定义spring配置元数据,可间接打消xml配置文件。例如:
- @Configuration
- @Bean
- @DependsOn
- @Primary
- @Lazy
- @Import
- @ImportResource
- @Value
如何应用XML 配置的形式配置Spring?
SpringXML 配置的次要目标时候是使所有的Spring 组件都能够用xml 文件的模式来进行配置。这意味着不会呈现其余的Spring 配置类型(比方申明的形式或基于Java Class 的配置形式)。
Spring 的XML 配置形式是应用被Spring 命名空间的所反对的一系列的XML 标签来实现的。Spring有以下次要的命名空间:context、beans、jdbc、tx、aop、mvc 和aso。
<beans> <!-- JSON Support --> <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/> <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/> </beans>
上面这个web.xml 仅仅配置了DispatcherServlet,这件最简略的配置便能满足应用程序配置运行时组件的需要。
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Spring 提供哪些配置模式?
依据[Pt6]的形容,Spring提供了3种配置模式。
Spring对Java配置的反对是由@Configuration注解和@Bean注解来实现的。由@Bean注解的办法将会实例化、配置和初始化一个新对象,这个对象将由Spring的IOC容器来治理。@Bean申明所起到的作用与XML元素相似。被@Configuration 所注解的类则示意这个类的次要目标是作为bean 定义的资源。被@Configuration申明的类能够通过在同一个类的外部调用@bean办法来设置嵌入bean 的依赖关系。
// 最简略的@Configuration 申明类请参考上面的代码: @Configuration public class AppConfig{ @Bean public MyService myService() { return new MyServiceImpl(); } }
对于下面的@Beans 配置文件雷同的XML 配置文件如下:
<beans> <bean id="myService" class="com.demo.services.MyServiceImpl"/> </beans>
上述配置形式的实例化形式如下:利用AnnotationConfigApplicationContext 类进行实例化
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); MyService myService = ctx.getBean(MyService.class); myService.doStuff(); }
要应用组件组建扫描,仅需用@Configuration 进行注解即可:
@Configuration @ComponentScan(basePackages = "com.demo") public class AppConfig { }
在下面的例子中,com.demo 包首先会被扫到,而后再容器内查找被@Component 申明的类,找到后将这些类依照Spring bean 定义进行注册。
怎么用注解的形式配置Spring?
Spring 在2.5 版本当前开始反对用注解的形式来配置依赖注入。
能够用注解的形式来代替XML形式的bean 形容,能够将bean 形容转移到组件类的外部,只须要在相干类上、办法上或者字段申明上应用注解即可。
注解注入将会被容器在XML 注入之前被解决,所以后者会笼罩掉前者对于同一个属性的处理结果。注解拆卸在Spring 中是默认敞开的。所以须要在Spring 文件中配置一下能力应用基于注解的拆卸模式。
如果你想要在你的应用程序中应用对于注解的办法的话,请参考如下的配置。
<beans> context:annotation-config/ </beans>
在标签配置实现当前,就能够用注解的形式在Spring 中向属性、办法和构造方法中主动拆卸变量。
上面是几种比拟重要的注解类型:
- @Required:该注解利用于设值办法。
- @Autowired:该注解利用于有值设值办法、非设值办法、构造方法和变量。
- @Qualifier:该注解和@Autowired 注解搭配应用,用于打消特定bean 主动拆卸的歧义。
- JSR-250 Annotations:Spring 反对基于JSR-250 注解的以下注解,@Resource、@PostConstruct和@PreDestroy。
请解释Spring Bean 的生命周期?
在一个bean 实例被初始化时,须要执行一系列的初始化操作以达到可用的状态。同样的,当一个bean 不在被调用时须要进行相干的析构操作,并从bean 容器中移除。SpringBeanFactory 负责管理在spring 容器中被创立的bean 的生命周期。Bean 的生命周期由两组回调(call back)办法组成。
- 初始化之后调用的回调办法。
- 销毁之前调用的回调办法。
Spring 框架提供了以下四种形式来治理bean 的生命周期事件:
- InitializingBean 和DisposableBean 回调接口
- 针对非凡行为的其余Aware 接口
- Bean 配置文件中的Custom init()办法和destroy()办法
- @PostConstruct 和@PreDestroy 注解形式
应用customInit()和customDestroy()办法治理bean 生命周期的代码样例如下:
`
`
<beans>
<bean id="demoBean" class="com.gupaoedu.task.DemoBean"
init-Method="customInit" destroy-Method="customDestroy">
</bean>
</beans>
# Spring Bean 作用域之间的区别?Spring 容器中的bean 能够分为5 个范畴。* singleton:这种bean 范畴是默认的,这种范畴确保不论承受到多少个申请,每个容器中只有一个bean 的实例,单例的模式由bean factory 本身来保护。* prototype:原形范畴与单例范畴相同,为每一个bean 申请提供一个实例。* request:在申请bean 范畴内会每一个来自客户端的网络申请创立一个实例,在申请实现当前,bean会生效并被垃圾回收器回收。* Session:与申请范畴相似,确保每个session 中有一个bean 的实例,在session 过期后,bean 会随之生效。* global-session:global-session 和Portlet 利用相干。当你的利用部署在Portlet 容器中工作时,它蕴含很多portlet。如果你想要申明让所有的portlet 共用全局的存储变量的话,那么这全局变量须要存储在global-session 中。全局作用域与Servlet 中的session 作用域成果雷同。 # 什么是Spring inner beans?在Spring 框架中,无论何时bean 被应用时,当仅被调用了一个属性(作为POJO类应用,仅提供属性的set/get能力,没有其它行为)。一个理智的做法是将这个bean申明为外部bean。外部bean 能够用setter 注入“属性”和构造方法注入“结构参数”的形式来实现。比方,在咱们的应用程序中,一个Customer 类援用了一个Person 类,咱们的要做的是创立一个Person的实例,而后在Customer 外部应用
public class Customer{
private Person person;
//Setters and Getters
}
public class Person{
private String name;
private String address;
private int age;
//Setters and Getters
}
<bean id="CustomerBean" class="com.howtodoinjava.common.Customer">
<property name="person">
<!-- This is inner bean -->
<bean class="com.howtodoinjava.common.Person">
<property name="name" value="lokesh" />
<property name="address" value="India" />
<property name="age" value="34" />
</bean>
</property>
</bean>
# Spring 框架中的单例Beans 是线程平安的么?Spring 框架并没有对单例bean 进行任何多线程的封装解决。对于单例bean 的线程平安和并发问题须要开发者自行去搞定。但实际上,大部分的Spring bean 并没有可变的状态(比方Serview 类和DAO类),所以在某种程度上说Spring 的单例bean 是线程平安的。如果你的bean 有多种状态的话(比方View Model 对象),就须要自行保障线程平安。最通俗的解决办法就是将多态bean 的作用域由“singleton”变更为“prototype”。 # 请举例说明如何在Spring 中注入一个Java 汇合?Spring 提供了以下四种汇合类的配置元素:* <list>标签用来拆卸可反复的list 值。* <set>标签用来拆卸没有反复的set 值。* ‘<map>该标签可用来注入键和值能够为任何类型的键值对。* <props>该标签反对注入键和值都是字符串类型的键值对。 ### 上面看一下具体的例子:
<beans>
<bean id="javaCollection" class="com.gupaoedu.JavaCollection">
<property name="customList">
<list>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</list>
</property>
<property name="customSet">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</set>
</property>
<property name="customMap">
<map>
<entry key="1" value="INDIA"/>
<entry key="2" value="Pakistan"/>
<entry key="3" value="USA"/>
<entry key="4" value="UK"/>
</map>
</property>
<property name="customProperies">
<props>
<prop key="admin">admin@gupaoedu.com</prop>
<prop key="support">support@gupaoedu.com</prop>
</props>
</property>
</bean>
</beans>
# 如何向Spring Bean 中注入java.util.Properties?应用如上面代码所示的标签:
<bean id="adminUser" class="com.gupaoedu.common.Customer">
<property name="emails">
<props>
<prop key="admin">admin@gupaoedu.com</prop>
<prop key="support">support@gupaoedu.com</prop>
</props>
</property>
</bean>
# 请解释Spring Bean 的主动拆卸?在Spring 框架中,在配置文件中设定bean 的依赖关系是一个很好的机制,Spring 容器还能够主动拆卸单干关系bean 之间的关联关系。这意味着Spring 能够通过向Bean Factory 中注入的形式主动搞定bean 之间的依赖关系。主动拆卸能够设置在每个bean 上,也能够设定在特定的bean 上。上面的XML 配置文件表明了如何依据名称将一个bean 设置为主动拆卸: <bean id="employeeDAO" class="com.gupaoedu.EmployeeDAOImpl" autowire="byName" /> 除了bean配置文件中提供的主动拆卸模式,还能够应用@Autowired注解来主动拆卸指定的bean。在应用@Autowired注解之前须要在依照如下的配置形式在Spring 配置文件进行配置才能够应用。 <context:annotation-config /> 也能够通过在配置文件中配置AutowiredAnnotationBeanPostProcessor 达到雷同的成果。 <bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> 配置好当前就能够应用@Autowired 来标注了。
@Autowired
public EmployeeDAOImpl ( EmployeeManager manager ) {
this.manager = manager;
}
# 主动拆卸有哪些局限性?主动拆卸有如下局限性:* 重写:你依然须要应用<property>设置指明依赖,这意味着总要重写主动拆卸。* 原生数据类型:你不能主动拆卸简略的属性,如原生类型、字符串和类。* 含糊个性:主动拆卸总是没有自定义拆卸准确,因而,如果可能尽量应用自定义拆卸。 # 请解释各种主动拆卸模式的区别?在Spring 框架中共有5 种主动拆卸,让咱们逐个剖析。* no:这是Spring 框架的默认设置,在该设置下主动拆卸是敞开的,开发者须要自行在bean 定义中用标签明确的设置依赖关系。* byName:该选项能够依据bean名称设置依赖关系。当向一个bean中主动拆卸一个属性时,容器将依据bean的名称主动在在配置文件中查问一个匹配的bean。如果找到的话,就拆卸这个属性,如果没找到的话就报错。* byType:该选项能够依据bean类型设置依赖关系。当向一个bean中主动拆卸一个属性时,容器将依据bean的类型主动在在配置文件中查问一个匹配的bean。如果找到的话,就拆卸这个属性,如果没找到的话就报错。* constructor:结构器的主动拆卸和byType模式相似,然而仅仅实用于与有结构器雷同参数的bean,如果在容器中没有找到与结构器参数类型统一的bean,那么将会抛出异样。* autodetect:该模式主动探测应用结构器主动拆卸或者byType主动拆卸。首先,首先会尝试找适合的带参数的结构器,如果找到的话就是用结构器主动拆卸,如果在bean 外部没有找到相应的结构器或者是无参结构器,容器就会主动抉择byTpe 的主动拆卸形式。 # 请举例解释@Required?@Required 正文利用于 bean 属性的 setter 办法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异样。上面显示的是一个应用 @Required 正文的示例。
// 应用Spring IoC实例化对象时,如果age和name未设置,将会报BeanInitializationException谬误
public class Student {
private Integer age;
private String name;
@Required
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
@Required
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
# 请举例说明@Qualifier?可能会有这样一种状况,当你创立多个具备雷同类型的 bean时,并且想要用一个属性只为它们其中的一个进行拆卸,在这种状况下,你能够应用@Qualifier 正文和 @Autowired 正文通过指定哪一个真正的 bean 将会被拆卸来打消凌乱。@Qualifier注解意味着能够在被标注bean的字段上依照名称进行主动拆卸。
public class Profile {
@Autowired
@Qualifier("student1")
private Student student;
public Profile(){
System.out.println("Inside Profile constructor." );
}
public void printAge() {
System.out.println("Age : " + student.getAge() );
}
public void printName() {
System.out.println("Name : " + student.getName() );
}
}
# 构造方法注入和设值注入有什么区别?### 相比而言设值(Setter)注入具备以下长处:* 与传统的JavaBean的写法更类似,程序开发人员更容易了解、承受。通过setter办法设定依赖关系显得更加直观、天然。* 对于简单的依赖关系,如果采纳结构注入,会导致结构器过于臃肿,难以浏览。Spring在创立Bean实例时,须要同时实例化其依赖的全副实例,因此导致性能降落。而是用设置注入能够防止这些问题。* 尤其在某些属性可选的状况下,多参数的结构器更加轻便。 ### 某些状况下,结构注入的劣势:* 结构注入能够再结构器中决定依赖关系的注入程序,无限依赖的优先注入。 例如,组件中其它依赖关系的注入,经常须要依赖于Datasource的注入。 采纳结构注入,能够在代码中清晰地决定注入程序。* 对于依赖关系无需变动的Bean,结构注入更加有用。因为没有setter办法,所有的依赖关系全副在结构器内设定。因而,无需放心后续代码对依赖关系的毁坏。* 依赖关系只能在结构器中设定,则只有组件的创建者能力扭转组件的依赖关系。对组件的调用者而言,组件外部的依赖关系齐全通明,更合乎高内聚的准则。 倡议:采纳设值注入为主,结构注入为辅的注入策略。对于依赖关系无需变动的注入,尽量采纳结构注入; 而其它的依赖关系的注入,则思考设值注入。 # Spring 框架中有哪些不同类型的事件?Spring 的ApplicationContext 提供了反对事件和代码监听器的性能。咱们能够创立bean 用来监听在ApplicationContext 中公布的事件。ApplicationEvent 类在ApplicationContext 接口中解决的事件,如果一个bean 实现了ApplicationListener 接口,当一个ApplicationEvent 被公布当前,bean 会主动被告诉。
public class AllApplicationEventListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
//process event
}
}
### Spring 提供了以下5 中规范的事件:* 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext 被初始化或者更新时公布。也能够在调用ConfigurableApplicationContext 接口中的refresh()办法时被触发。* 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext 的Start()办法开始/从新开始容器时触发该事件。* 上下文进行事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext 的Stop()办法进行容器时触发该事件。* 上下文敞开事件(ContextClosedEvent):当ApplicationContext 被敞开时触发该事件。容器被敞开时,其治理的所有单例Bean 都被销毁。* 申请处理事件(RequestHandledEvent):在Web 利用中,当一个http 申请(request)完结触发该事件。 除了下面介绍的事件以外,还能够通过扩大ApplicationEvent 类来开发自定义的事件。
public class CustomApplicationEvent extends ApplicationEvent {
public CustomApplicationEvent ( Object source, final String msg ){
super(source);
System.out.println("Created a Custom event");
}
}
为了监听这个事件,还须要创立一个监听器:
public class CustomEventListener implements ApplicationListener < CustomApplicationEvent >{
@Override
public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
}
}
之后通过applicationContext 接口的publishEvent()办法来公布自定义事件。
CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext,“Test message”);
applicationContext.publishEvent(customEvent);
# FileSystemResource 和ClassPathResource 有何区别?在FileSystemResource 中须要给出spring-config.xml 文件在你我的项目中的相对路径或者绝对路径。在ClassPathResource 中spring 会在ClassPath 中主动搜查配置文件,所以要把ClassPathResource 文件放在ClassPath 下。如果将spring-config.xml 保留在了src 文件夹下的话,只需给出配置文件的名称即可,因为src 文件夹是默认。简而言之,ClassPathResource 在环境变量中读取配置文件,FileSystemResource 在配置文件中读取配置文件。 # Spring 框架中都用到了哪些设计模式?Spring 框架中应用到了大量的设计模式,上面列举了比拟有代表性的:* 代理模式:在AOP 和remoting 中被用的比拟多。* 单例模式:在spring 配置文件中定义的bean 默认为单例模式。* 模板模式:用来解决代码反复的问题。比方. RestTemplate, JmsTemplate, JpaTemplate。* 委派模式:Srping 提供了DispatcherServlet 来对申请进行散发。* 工厂模式:BeanFactory 用来创建对象的实例,贯通于BeanFactory / ApplicationContext 接口的核心理念。* 代理模式:AOP 思维的底层实现技术,Spring 中采纳JDK Proxy 和CgLib 类库。 # 在Spring 框架中如何更无效的应用JDBC?应用Spring JDBC 框架,资源管理以及错误处理的代价都会加重。开发人员只需通过statements 和queries 语句从数据库中存取数据。Spring框架中通过应用模板类能更无效的应用JDBC,也就是所谓的JdbcTemplate。 # 请解释下Spring框架中的IOC容器?* Spring中的 org.springframework.beans 包和 org.springframework.context包形成了Spring框架IoC容器的根底。* BeanFactory接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。* ApplicationContex接口对BeanFactory(是一个子接口)进行了扩大,在BeanFactory的根底上增加了其余性能,比方与Spring的AOP更容易集成,也提供了解决messageresource的机制(用于国际化)、事件流传以及应用层的特地配置,比方针对Web利用的WebApplicationContext。* org.springframework.beans.factory.BeanFactory 是Spring IoC容器的具体实现,用来包装和治理后面提到的各种bean。BeanFactory接口是Spring IoC容器的外围接口。 # 在Spring 中能够注入null 或空字符串吗?齐全能够。<null/>用于解决null值。Spring会把属性的空参数当作空字符串解决。以下的xml片断将email属性设为空字符串。
<bean class="ExampleBean">
<property name="email"><value/></property>
</bean>
这等同于Java代码: exampleBean.setEmail("")。而null值则能够应用<null>元素可用来示意。例如:
<bean class="ExampleBean">
<property name="email"><null/></property>
</bean>
上述的配置等同于Java代码:exampleBean.setEmail(null)。# 最初