现在基本上企业开发标配都是Spring5+Springboot2+Jdk7
1.Spring的优点
- IOC和DI的支持:Spring的核心是一个工厂容器,可以维护所有对象的创建和依赖关系,Spring工厂用于生成bean,并且管理Bean的生命周期, 实现高内聚低耦合的设计理念。
- AOP编程的支持:Spring提供面向切面编程,可以方便的实现对程序的权限拦截,运行切面等功能。
- 声明式事务支持:支持通过配置就来完成对事务的管理,而不需要通过硬编码的方式,以前重复的一些事务提交,回滚的JDBC代码
- 快捷测试的支持:Spring对Junit提供支持,可以通过注解快捷的测试Spring程序。
- 快速的集成开发:方便集成各种开发框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持。
- 复杂的API模板封装:Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了模板化的封装,这些封装 API的提供使得应用难度大大降低。
2.Spring有哪些模块
主要的7大模块:
- Spring Core:Spring核心,他是框架最基础的部分,提供IOC和依赖注入DI的特性
- Spring Context :Spring上下文容器,它是BeanFactory功能加强的一个子接口。
- Spring Web:它提供Web应用开发的支持。
- SpringMVC :它针对Web应用中MVC思想的实现。
- SpringDAO:提供了JDBC抽象层,简化了JDBC编码
- Spring ORM:它支持用于流行的OPRM框架整合,比如:Spring + Hibernate、Spring + iBatis、Spring + JDO 的整合等。
- Spring AOP:即面向切面编程,它提供了与AOP联盟兼容的编程实现
3.Spring有那些注解。
容器
- @Component:表示一个带注释的类是一个“组件”,成为 Spring 管理的 Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时@Component 还是一个元注解。
- @Service:组合注解(组合了@Component 注解),应用在 service 层(业务逻辑层)。
- @Repository:组合注解(组合了@Component 注解),应用在 dao 层(数据访问层)。
- @Autowired:Spring 提供的工具(由 Spring 的依赖注入工具(BeanPostProcessor、 BeanFactoryPostProcessor)自动注入)。
- @Qualifier:该注解通常跟 @Autowired 一起使用,当想对注入的过程做更多的控制,@Qualifier 可帮助配置,比如两个以上相同类型的 Bean 时 Spring 无法抉择,用到此注解
- @Configuration:声明当前类是一个配置类(相当于一个 Spring 配置的 xml 文件)
- @Value:可用在字段,构造器参数跟方法参数,指定一个默认值,支持SpringbBoot 中的application.properties 配置的属性值赋值给变量
- @Bean:注解在方法上,声明当前方法的返回值为一个 Bean。返回的 Bean 对应的类中可以定义 init()方法
和 destroy()方法,然后在 @Bean(initMethod=”init”,destroyMethod=”destroy”)定义,在构造之后执行 init,在销毁之前执行 destroy。 - @Scope:定义我们采用什么模式去创建 Bean(方法上,得有@Bean) 其设置类型包括:Singleton 、
Prototype、Request 、 Session、GlobalSession。
AOP:
- @Aspect:声明一个切面(类上) 使用@After、@Before、@Around 定义建言(advice),可直接将拦截规则(切点)作为参数。
- @After:在方法执行之后执行(方法上)。
- @Before: 在方法执行之前执行(方法上)。
- @Around: 在方法执行之前与之后执行(方法上)。
- @PointCut: 声明切点 在 java 配置类中使用@EnableAspectJAutoProxy 注解开启 Spring 对 AspectJ
代理的支持(类上)。
事务:
- @Transactional:在要开启事务的方法上使用@Transactional 注解,即可声明式开启事务。
4.Spring的常用注解
- 工厂模式:Spring本质上就是一个大工厂,使用工厂模式通过BeanFactory,ApplicationContent创建bean对象
- 代理模式:Spring Aop功能就是通过代理模式实现的,分为动态代理和静态代理
- 单例模式:Spring 中的Bean默认都是单例的,这样有利于容器对Bean的管理。
- 模板模式:Spring中的JdbcTemplate,RestTemplate等以Template结尾的对数据库,网络等操作的模板类,就是使用到了模板模式。
- . 适配器模式 :Spring AOP 的增强或通知 (Advice) 使用到了适配器模式、Spring MVC 中也是用到了适配器模式适配 Controller。
- 策略模式:Spring中有一个Resource接口,它的不同实现类,会根据不同的策略去访问资源。
5.什么事IOC,什么是DI
- 所谓的IOC(控制反转),就是由容器来负责控制对象的生命周期和对象的关系,以前是我们想要什么就创建什么,现在是我们需要什么就送来什么。
也就是说,控制对象的生命周期的不再引用它的对象,而是容器。对具体的对象以前是它控制其他对象,现在所有对象都被容器控制,所以这叫控制反转。
2.DI(依赖注入):指的是容器在实例化对象的时候把它依赖的类注入给它,有的说法是DI和IOC是一回事,也有说法IOC是思想,DI是IOC的实现类。
为什么要用IOC呢
最主要的是为了解耦,硬编码会造成对象之间的过度耦合,使用了IOC之后,我们就不要关心对象之间的依赖,专心开发应用就行。
6.能简单说一下 SpringIOC的实现机制吗?
PS:这道题在面试中被问到过,问法是“你有自己实现过简单的 Spring 吗?”
7.说说BeanFactory和ApplicantContext?
可以这么形容,BeanFactory是Sprin的心脏,Applicantext是完整的身躯
- BeanFactory(Bean工厂)是Spring框架的的基础设施,面向Spring本身
- ApplicantContext是建立在BeanFactory的基础上,面向使用的Spring框架的开发者。
BeanFactory接口
BeanFactory是类的通用工厂,可以创建并且管理各种类的对象
Spring为BeanFactory提供了很多种实现,最常用的是xmlBeanFactory,但是在Spring3.2中已被废弃,建议使用XmlBeanDefinitonReader,DefaultListBeanFactory
- BeanFactory接口位于类结构树的顶端,它最主要的方法是getBean(String var)这个方法从特定容器中返回特定名称的Bean。
- BeanFactory 的功能通过其它的接口得到了不断的扩展,比如 AbstractAutowireCapableBeanFactory 定义了将容器中的
Bean 按照某种规则(比如按名字匹配、按类型匹配等)进行自动装配的方法。
ApplicationContext接口
ApplicationContext是由BeaFactory派生而来,提供更多了面向实际的功能,可以这么说,使用
BeanFactory 就是手动档,使用 ApplicationContext 就是自动档。
ApplicationContext 继承了HierachicalBeanFactory 和 ListableBeanFactory 接口,在此基础上,还通过其他的接口扩展
了BeanFactory 的功能,包括:
- Bean instantiation/wiring
- Bean 的实例化/串联
- 自动的 BeanPostProcessor 注册
- 自动的 BeanFactoryPostProcessor 注册方便的 MessageSource 访问(i18n)
- ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在ApplicationContext 启动之后实例化
这是 ApplicationContext 的使用例子
public class HelloWorldApp{
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
ApplicationContext包含了BeanFactory的所有特性,所以一般推荐使用前者
8. 你知道Spring容器启动阶段会干什么吗
Spring的IOC容器工作过程,其实可以分为两阶段,容器启动阶段和Bean的实例化阶段,其中容器启动阶段主要工作是加载和解析配置文件,保存到对应的Bean中。
容器 启动阶段,首先会通过某种途径加载Congiguration MetaData,在大部分情况下,容器需要依赖某些工具类,对加载的Conguguration MetaData进行解析和分析,并将分析后的信息组织为相应的BeanDefinition。
最后把这些的Bean定义必要信息的BeanDefiniton,注册到相应的BeanDefinitionRegistry,这样容器就完成了
9.能说下SpringBean的生命周期吗
SpringIOC的生命周期大致分为 实力化、属性赋值、初始化、销毁
10.Bean定义和依赖定义有哪几种方式
有三种方式: 直接编码方式、配置文件方式、注解方式。
- 直接编码方式:我们一般接触不到直接编码方式,但是其他方式最终都要通过直接编码来实现。
- 配置文件方式:通过XML、propreties类型的配置文件,配置相应的依赖关系,Spring读取配置文件,完成依赖关系的注入。
- 注解方式:注解方式应该是我们用过最多的一种方式,在相应的地方进行注解,Spring会扫描注解,完成依赖关系的注入。
11 有哪些 依赖注入的方法
Spring支持的构造方法注入、属性注入、工厂方法注入、其中工厂方法注入又可以分为 静态工厂注入和非静态方法注入。
12.Spring有那些自动装配的方式
Spring提供了4种自动装配类型:byType,byName,constructor,autodetect
- byName:根据名称进行自动匹配,假设 Boss 又一个名为 car 的属性,如果容器中刚好有一个名为 car 的bean,Spring就会自动将其装配给 Boss 的 car 属性
- byType:根据类型进行自动匹配,假设 Boss 有一个 Car 类型的属性,如果容器中刚好有一个 Car 类型的Bean,Spring 就会自动将其装配给 Boss 这个属性
- constructor:与 byType 类似, 只不过它是针对构造函数注入而言的。如果 Boss 有一个构造函数,构造函数包含一个 Car 类型的入参,如果容器中有一个 Car 类型的 Bean,则 Spring 将自动把这个 Bean 作为 Boss构造函数的入参;如果容器中没有找到和构造函数入参匹配类型的 Bean,则 Spring 将抛出异常。
- autodetect:根据 Bean 的自省机制决定采用 byType 还是 constructor 进行自动装配,如果 Bean 提供了默认的构造函数,则采用 byType,否则采用 constructor。
13.Spring中的Bean的作用域
14.Spring中的单例Bean存在线程安全吗
Spring中的Bean不是线程安全的。
因为单例Bean,是全局只有一个 Bean,所有线程共享。如果说单例Bean,是一个无状态的,也就是线程中的操作不会对 Bean 中的成员变量执行查询以外的操作,那么这个单例Bean 是线程安全的。比如 Spring mvc 的 Controller、
Service、Dao 等,这些 Bean 大多是无状态的,只关注于方法本身。
假如这个 Bean 是有状态的,也就是会对 Bean 中的成员变量进行写操作,那么可能就存在线程安全的问题。
常见的解决方法:
1.将Bean定义为多例:这样每一个线程请求都会创建一个Bean,但是这样就不好管理了,不能这样干
2。在bean对象中尽量避免定义可变的成员变量,但是这不符合开发要求,也不能这样干。
3.将Bean中成员变量保存在ThreadLocal中。
因为ThreadLocal能保证多线程下的变量隔离可以在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在Threadlocal中,这个是推荐使用的方式。
15.@Autowired的实现原理。
实现@Autowired的关键是AutowiredAnnotationBeanPostProcessor
在Bean的初始化阶段,会通过Bean后置处理器来进行一些前置和后置的处理,实现@Autowired的功能,也是通过后置处理器来完成了,这个后置处理器就是AutowiredAnnotationBeanPostProcessor
-Spring在创建 bean的过程中,最终会调用到 doCreateBean()方法,在 doCreateBean()方法中会调用populateBean()方法,来为 bean 进行属性填充,完成自动装配等工作。
- 在 populateBean()方法中一共调用了两次后置处理器,第一次是为了判断是否需要属性填充,如果不需要进行属性
填充,那么就会直接进行return,如果需要进行属性填充,那么方法就会继续向下执行,后面会进行第二次后
置处理器的调用,这个时候,就会调用到 AutowiredAnnotationBeanPostProcessor 的 postProcessPropertyValues()方法,在该方法中就会进行@Autowired 注解的解析,然后实现自动装配