一、概念
Spring是一个开源容器框架,可以接管web层,业务层,dao层,持久层的组件,并且可以配置各种bean,和维护bean与bean之间的关系。其核心就是控制反转(IOC),和面向切面(AOP),简单的说就是一个分层的轻量级开源框架。
二、核心原理
1、 IOC控制反转
控制权由对象本身转向容器,由容器根据配置文件创建对象实例并实现各对象间的依赖关系。
核心:bean工厂
DI:依赖注入(三种注入方式:构造函数、setter方法、基于注解)
2、AOP面向切面编程
a、静态代理
b、动态代理
Jdk动态代理:针对一方面编写一个InvocationHandler,然后由JDK反射包中的Proxy类为各接口动态生成相应的代理类。
三、问题清单
1、使用spring框架的好处有哪些?
- 轻量:Spring 是轻量的,基本的版本大约2MB。
- 控制反转IOC:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
- 面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
- 容器:Spring 包含并管理应用中对象的生命周期和配置。
- MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
- 事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
2、BeanFactory和ApplicationContext的区别?(IOC如何实现的?)
1)、BeanFactory当调用时,读取配置信息,生成某个类的实例;
BeanFactory factory= new XmlBeanFactory(new ClassPathResource("applicaitonContext.xml"));
factory.getBean("student"); //取bean的时候才会实例化
2)、ApplicationContext 在初始化时,就把 xml 的配置信息读入内存,创建所有的Bean;
ApplicationContext ac = new ClassPathXmlApplicationContext("applicaitonContext.xml");
ApplicationContext扩展了BeanFactory,唯一的不足是占用内存空间,启动较慢
ApplicationContext其他功能:支持国际化文本消息;
统一的资源文件读取方式;
已在监听器中注册bean的事件;
ApplicationContext三种实现:
- FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
- ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。
- WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。
3、spring的几种配置方式?
基于xml配置:<beans/><beans>
基于注解配置:@Autowired,@Required,@Qualifier
基于java配置:由@Configuration注解和@Bean注解实现;
4、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()方法。
5、bean的作用域
Singleton:单例模式(默认)容器中只有一个实例;
Protptype:原型模式,每次获取bean时,都创建一个新的bean实例;
Request:在一次http请求中,容器会返回该bean的同一实例,不同请求会创建新实例;
Session:再一次http session中,容器会返回该bean的同一实例,不同session请求会创建新实例;
Global session:在一个全局的Http Session中,容器会返回该Bean的同一个实例,仅在使用portlet context时有效。
6、spring框架中用的哪些设计模式?
代理模式:AOP(jdk动态代理和cglib代理);
单例模式:spring配置文件中定义的bean默认为单例;
依赖注入:贯穿beanFactory和ApplicationContext接口的核心;
工厂模式:BeanFactory用来创建对象的实例;
7、请解释spring自动装配模式的区别?(能够自动装配相互合作的bean)
No:默认关闭;
byName:根据bean名称设置依赖关系;
byType:根据bean类型设置依赖关系;
Constructor:与byType类似,与有构造器相同参数的bean;
Autodetect:自动探测,先用构造器自动装配,再用byType;
8、说下AOP及其实现原理(用于日志、校验)
AOP为面向切面编程,其有两种动态代理方式:
Jdk动态代理:通过反射来接收被代理类,要求被代理类必须实现一个接口,其核心是InvocationHandler接口和Proxy类;
为什么 Jdk动态代理需要使用接口?
因为在继承proxy类获得有关方法和InvocationHandler构造方法传参的同时,java不能同时继承两个类,我们需要和想要代理的类建立联系,只能实现一个接口
Cglib,若目标类没有实现接口,aop会选择cglib动态代理目标类,其通过继承的方式来动态代理,若目标类被标记为final,则无法用cglib动态代理,因为cglib是通过生成子类对象来调用目标对象的方法;
9、spring事务底层原理
Spring并不直接管理事务,Spring事务管理器的接口是PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器:
JDBC:DataSourceTransactionManager
XML将其装配到应用程序的上下文定义中:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
声明式事务:基于<tx> 和 <aop> 命名空间的xml配置文件:管理建立在AOP之上的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
基于@Transactional注解(只能用再public 方法上,由 Spring AOP 的本质决定的);
将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。显然基于注解的方式更简单易用,更清爽
@Transactional(rollbackFor = Exception.class)
Spring AOP其实是与IOC配合使用的,而Spring AOP是用动态代理的技术。也就是说一个类被IOC所注入生成的对象被Spring动态代理成一个新的代理对象。
同一个类里的无事务注解的A方法调用事务注解的B方法,B方法事务无效,因为如果我们在外部调用这个动态代理对象,会在代理的时候增强对象,但在对象的内部调用的时候,调用的还是原来的对象的方法,该方法明细不会被AOP增强。
编程式事务:通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
10、如何自定义注解实现功能?
public @interface Transactional{}
和创建接口类似,在interface前加@,
注解方法不可带参数;注解方法返回值限定基本类型、string、enums、Annotation或者这些类型的数组;注解方法有默认值;
11、Spring使用异步注解@Async
注意的点
* 必须用在public方法上
* 在某异步方法的同一个类的其他方法调用此异步方法无效
*异步方法使用注解@Async的返回值只能为void或者Future
在@SpringBootApplication启动类当中添加注解@EnableAsync注解
Spring默认用SimpleAsyncTaskExecutor来处理@Async注解的任务