1、BeanFactory和ApplicationContext区别
- 特性不同 BeanFactory提供了高级配置机制和基础功能(只提供了ioc/di支持,常用的是XmlBeanFactory),ApplicationContext是BeanFactory的子接口,增加了企业特定功能(常用的是ClassPathApplicationContext):
- 更容易与spring aop功能集成
- 继承messageRsource接口,用于国际化
- 继承事件发布接口
- 应用层的上下文,如webApplicationContext
-
对bean的加载方式不同 BeanFactory是懒加载,在调用getBean时才实例化bean ApplicationContext是预加载,在应用启动后就加载所有的bean
-
应用场景不同 BeanFactory适合系统资源较少的环境中使用延迟实例化,如移动应用中。 ApplicationContext适合企业级的大型web应用,在启动时完成耗时操作。
2、BeanFactory 和 FactoryBean
- BeanFactory是spring的ioc容器,用于管理bean的创建销毁的。
- FactoryBean是用于构建复杂的bean,相对于在xml配置中使用标签方便容易的定义bean,有时创建bean有更复杂的逻辑,则使用FactoryBean。用ioc容器获取FactoryBean时,实际获取的是FactoryBean实际要创建的Bean。
3、bean的生命周期(问这个的意义是理解spring的扩展点)
- 对象的生命周期一般是 实例化 初始化 接受请求 销毁 (如servlet)
- spring中的bean是实例化 设置属性 初始化 使用 销毁。 在实例化前后,设置属性前后,初始化前后都有扩展点。初始化完成后,如果是单例bean,bean会存入缓存,并在容器销毁时调用bean的销毁方法,如果是原型bean,则将bean交给用户,剩下的生命周期由用户控制。
4、spring怎么解决循环依赖
a对象实例化时,将a对象工厂放进三级缓存map。a对象填充属性时触发b对象实例化,b实例化时将b对象工厂放进三级缓存map,b填充属性时查找a对象时,从三级缓存map中获取a的对象工厂,并将三级缓存中的a对象工厂移除,将刚初始化完成的a对象/a代理对象放入二级缓存map并返回。b创建完成放入一级缓存,然后a从一级缓存中获取b填充属性完成,创建完成。
5、为什么解决循环依赖要用三级缓存
简答:二级缓存可以解决循环依赖,多加一级缓存是用于暂存初始化过程的代理对象。
三级缓存保存的数据分别是:
- 一级=完全创建好的对象,
- 二级=实例化的对象/代理对象,
- 三级=bean对象工厂。
bean创建过程中,bean对象工厂获取对象会判断是否需要代理,如果需要则返回代理对象,或者返回bean本身对象。如果不要第二级缓存,当多个对象用到三级缓存中的对象工厂生成代理类时会产生多个导致问题。所以得需要第二级缓存来暂存生成得代理对象,防止生成多个代理对象破坏单例。
假设不要第二级缓存,在第三级缓存中不放对象工厂,而是放对象工厂生成得对象或代理对象,也可以解决循环依赖。但是问题有2点: 1、第三级缓存中存在2种类型对象。2、代理对象等后置处理操作本应在初始化后,此时后置处理操作在实例化后。这2点都违反设计原则。
6、bean实例化的三种方式
- 构造器 指定class
- 静态工厂方法 指定class和静态工厂方法
- 实例工厂方法 定义和指定工厂bean及工厂方法
7、依赖注入的几种方式
- 构造器注入
- setter注入
- 自动装配
8、说下对AOP的理解(先问spring的动态代理实现aop 然后问AspectJ的了解,然后问javaagent)
AOP是面向切面编程
spring的AOP是基于动态代理实现的。默认使用jdk动态代理,jdk动态代理能对实现了接口的类创建代理对象。否则使用cglib对被代理对象创建一个子类作为代理。
spring aop的连接点 仅支持方法执行,如果需要建议字段访问和更新连接点,请考虑使用 AspectJ 之类的语言。spring aop不提供最完整的 AOP 实现,只为企业应用程序中的大多数问题提供了极好的解决方案。
AspectJ是java中功能全面的AOP框架,提供编译期织入,编译后织入,类加载时织入。因为是运行前,已把增强代码织入被增强类,属于静态织入,性能更好。编译期织入,编译后织入是ajc编译器实现。加载时织入(Load-Time Weaving)是在启动的时候指定agent来实现。
java探针技术:在JDK1.5以后,我们可以使用agent技术构建一个独立于应用程序的代理程序(即为Agent),用来协助监测、运行甚至替换其他JVM上的程序。使用它可以实现虚拟机级别的AOP功能。
Java ASM和Java Agent这两者之间是什么关系呢? Java ASM是一个操作字节码的工具(tool),而Java Agent提供了修改字节码的机会(opportunity)。 想像这样一个场景: 有一个JVM正在运行,突然Java Agent在JVM上打开一扇大门,Java ASM通过大门冲进JVM里面,就要开始修改字节码了。
AspectJ参考文档 https://www.jianshu.com/p/3c5b09f6f563
java agent参考文档 https://www.jianshu.com/p/63c328ca208d
9、说说对事务的理解,和在spring中的使用?
事务是数据库并发的最小控制单位,是一组要么都执行,要么都不执行的命令。 事务的特性包括:原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)
mysql数据库的隔离级别:
-
读未提交 (存在三个问题:脏读 不可重复读 幻读) -
读已提交 (存在两个问题:不可重复读 幻读) -
可重复读 (存在一个问题:幻读) -
串行化 (解决了以上三个问题,单事务串行执行,效率低)
spring的事务一般使用声明式的注解控制,可以放在类上或方法上。使用实例:
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
spring的事务隔离级别:
required:支持加入事务,没有则创建事务
requires_new:创建一个新事务,如果已有事务,则挂起已有事务
supports:有则加入当前事务,没有则无事务执行
mandatory:加入当前事务,没有则抛出异常
not_supported:有事务则挂起,以无事务执行
nerver:不支持当前事务,有事务抛出异常
nested:嵌套事务
10、springboot启动过程
1、初始化配置:通过类加载器,读取classpath下所有的spring.factories配置文件,创建初始配置对象和监听器;通知监听者应用程序启动开始;创建用于读取配置(application.yml)的环境对象environment。
2、创建应用程序上下文createApplicationContext():默认创建的是AnnotationConfigServletWebServerApplicationContext,此类有个超父类是GenericApplicationContext,因为创建对象时先运行父类的构造方法,所以创建了beanFactory。
3、刷新上下文refreshContext(): 3.1 配置工厂对象,包括设置类加载器,添加beanPostProcesser 3.2 注册并实例化beanFactoryPostProcesser,并且调用这些处理器,对包扫描解析。 3.3 注册并实例化beanPostProcesser 3.4 初始化一些与山下问特别有关系的bean对象(创建tomcat服务器) 3.5 实例化所有bean工厂缓存的bean对象 3.6 发布通知-通知上下文刷新完成(启动tomcat服务器)
4、通知监听者listeners.started(): 启动程序完成。
参考文档: https://www.cnblogs.com/Narule/p/14253754.html
11、springboot自动装配是怎么实现的?
-
启动主类上的注解@SpringBootApplication包含三个注解,其中一个是@EnableAutoConfiguration
-
此注解@EnableAutoConfiguration自动装配核心功能的实现是通过注解@Import(AutoConfigurationImportSelector.class),AutoConfigurationImportSelector实现了ImportSelector接口,作用是获取符合条件的类的全限定名,加载到ioc容器中。selectImports -> getAutoConfigurationEntry -> getCandidateConfigurations -> SpringFactoriesLoader.loadFactoryNames()获取所有自动配置类
-
根据自动配置类上的条件注解ConditionalOnClass判断是否生效,生效则加载bean到容器
12、springboot如何自定义starter?
-
创建maven工程 添加自动配置类
-
meta-info目录下的spring.factories文件里加入自动配置的键值对,key是EnableAutoConfiguration的全限定名,value是自定义配置类的全限定名。
-
自定义配置中根据条件(类是否存在等)创建bean
-
用ConfigurationProperties定义属性类,EnableConfigurationProperties启动属性配置,来加载配置文件中的值,并可用作自定义配置类中的条件。
13、springboot如何打包成war包?
- pom文件中修改打包方式为war
<packaging>war</packaging>
- 去除内嵌的tomcat依赖,并添加范围是providedtomcat依赖,用于启动时提供编译支持。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
- 添加一个继承SpringBootServletInitializer类,并且覆盖configure方法
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(JarTowarDemoApplication.class);
}
}
- 如果需要修改打出的war包名,添加如下插件(主要是默认的会带0.0.1-SNAPSHOT)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warSourceExcludes>src/main/resources/**</warSourceExcludes>
<warName>springboot</warName>
</configuration>
</plugin>