1.什么是BeanDefinition?
BeanDefinition表示Bean定义,Spring根据BeanDefinition来创建对象
BeanDefinition重要属性:
-
beanClass:表示一个类的类型,Spring在创建过程中会根据此属性来实例化得到对象
-
scope:表示一个bean的作用域,例如:scope为singleton表示该bean是一个单例bean,scope为prototype表示该bean是一个原型bean
-
isLazy:表示一个bean需不需要懒加载,懒加载的bean会在第一次getBean的时候生成bean,非懒加载的bean会在spring启动过程中直接生成好,原型bean的islazy属性不起作用(懒加载是针对单例bean的)
-
dependsOn:表示一个bean在创建之前所依赖的其它bean,在一个bean创建之前,它所依赖的这些bean的先全部创建好
-
primary:表示一个bean是主bean,在Spring中一个类型可以有多个bean对象,在进行依赖注入时,如果根据类型找到了多个bean,此时会判断这些bean中是否存在一个主bean,如果存在,则直接将这个bean主入给属性
-
initMethodName:表示一个bean的初始化方法,一个bean的生命周期过程中有一个步骤加初始化,Spring会在这个步骤中调用bean的初始化方法,初始化逻辑由程序员自己控制,表示程序员可以自定义逻辑对bean进行加工
在工作中使用到的@Component、@Bean、这些都会解析为BeanDefinition
2.什么是BeanFactory?
BeanFactory是一种“Spring容器”,BeanFactory翻译过来是Bean工厂,它可以用来创建Bean、获取Bean,BeanFactory是Spring中非常核心的组件
BeanDefination、BeanFactory、Bean对象三者之间的关系:
BeanFactory将利用BeanDefinition来生成Bean对象,BeanDefinition相当于BeanFactory的原材料,Bean对象就相当于BeanFactory生产出来的产品
BeanFactory的核心子接口和实现类:
- ListableBeanFactory
- ConfigurableBeanFactory
- AutowireCapableBeanFactory
- AbstractBeanFactory
- DefaultListableBeanFactory:支持单例Bean、支持Bean别名、支持父子BeanFactory、支持Bean类型转换、支持Bean后置处理、支持FactoryBean、支持自动装配等等
3.什么是Bean生命周期?
Bean生命周期描述的是Spring中一个Bean创建过程和销毁过程中所经历的步骤,其中Bean创建过程是重点,程序员可以利用Bean生命周期机制对Bean进行自定义加工
Bean生命周期核心步骤:
- BeanDefinition,Bean定义:BeanDefinition表示Bean定义,它定义了某个Bean的类型,Spring就是利用BeanDefinition来创建Bean的,比如需要利用BeanDefinition中beanClass属性确定Bean的类型,从而实例化出对象
- 构造方法推断选出一个构造方法:一个Bean中有多个构造方法,Spring来推断到底使用哪个构造方法
- 实例化,构造方法反射得到对象:通过构造方法反射得到一个实例化对象,在Spring中,可以通过BeanPostProcessor机制对实例化进行干预
- 属性填充,给属性进行自动填充:实例化所得到的对象,是不完整的对象,不完整的意思是该对象中的某些属性还没有进行属性填充,也就是Spring还没有自动给某些属性赋值,属性填充就是我们通常所说的自动注入、依赖注入
- 初始化,对其他属性进行赋值校验:在一个对象属性填充之后,Spring提供的初始化机制,程序员可以利用初始化机制对Bean进行自定义加工,比如可以利用initializingBean接口来对Bean中其它属性进行赋值,或对Bean中的某些属性进行校验
- 初始化后AOP生成代理对象:初始化后Bean创建生命周期最后一个步骤,我们常说AOP机制,就是在这个步骤中通过BeanPostProcessor机制实现的,初始化后得到的对象才是真正的Bean对象
4.@Autowired是什么?
@Autowired表示某个属性是否需要进行依赖注入,就可以写在属性和方法上。注解中required属性默认为true,表示如果没有对象可以注入给属性则跑异常。
- @Autowired加在某个属性上,Spring在进行Bean生命周期的过程中,在属性填充这一步,会基于实例化出来的对象,对该对象中加了@Autowire的属性自动给属性赋值。Spring会根据属性的类型去Spring容器中找出所有Bean对象,如果找出来多个,在根据属性的名字从多个中确定一个。如果required属性为true,并且根据属性信息找不到对象,则直接抛异常。(主要步骤,完整的底层筛选逻辑更多,不仅只有这两步)
- @Autowired注解写在某个方法上时,Spring在Bean生命周期的属性填充阶段,会根据方法的参数类型、参数名字从Spring容器中找到对象当作方法入参,自动反射调用该方法
- @Autowired注解加在构造方法上时,Spring会在推断构造方法阶段,选择该构造方法来进行实例化,在反射调用构造方法之前,会先根据构造方法参数类型、参数名从Spring容器中找到Bean对象,当做构造方法入参
5.@Resource是什么?
@Resource注解与@Autowired类似,也是用来依赖注入的,@Resource是Java层面所提供的注解,@Autowired是Spring所提供的注解,它们依赖注入的底层逻辑也不同。
@Resource注解中有一个属性、针对name属性是否有值,@Resource的依赖注入底层流程是不同的。@Resource如果name属性有值,那么Spring会直接根据所指定的name值去Spring容器中找Bean对象,如果找到了则成功,没找到则报错。@Resource中name属性没有值,则先判断属性名字在Spring容器中是否存在Bean对象,如果存在,则成功找到Bean对象进行注入,如果不存在,则根据属性类型去Spring容器中找Bean对象,找到一个则进行注入
6.@Value是什么
@Value注解和@Resource、@Autowired类似,也是用来对属性进行依赖注入的,只不过@value是用来从Properties文件中来获取值的,并且@Value可以解析SpEL(Spring表达式)
@Value(“str_aaa”):会把字符串str_aaa进行注入,如果属性类型不是String,并且无法进行类型转化则报错
@Value(" s t r a a a " ) : 将 会 把 {str_aaa}"):将会把 straaa"):将会把{}中的字符串当做key,从Properties文件中找出对应的value赋值给属性,如果没找到,则会把${str_aaa}当作值注入给属性
@Value("#{strAaa}"):会将#{}中的字符串当作Spring表达式进行解析,Spring会把strAaa当作beanName,并从Spring容器中找对应bean,如果找到则进行属性注入,没找到则报错
7.FactoryBean是什么?
FactoryBean是Spring所提供的一种灵活的创建Bean的方式,可以通过实现FactoryBean接口的getObject()方法来返回一个对象,这个对象就是Bean对象。FactoryBean对象本身也是一个Bean,同时相当于一个小型工厂,可以生产出另外的Bean。BeanFactory是一个Spring容器,是一个大型工厂,可以生产出各种各样的Bean。
- Object getObject():返回的是Bean对象
- boolean isSingleton(): 返回的是否是单例Bean对象
- Class getObjectType():返回的是Bean对象的类型
@Service("testService")
public class TestService implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
上述代码实际生成可两个Bean对象:
1.beanName为"testService",bean对象为getObject()方法返回的User对象
2.beanName为"&testService",bean对象为TestService类的实例对象
8.ApplicationContext是什么
ApplicationContext是比BeanFactory更加强大的Spring容器,它既可以创建bean、获取bean,还支持国际化、事件广播、获取资源等BeanFactory不具备的功能。
ApplicationContext所继承的接口
-
EnvironmentCapable:ApplicationContext继承了这个接口,表示拥有了获取环境变量的功能,可以通过ApplicationContext获取操作系统环境变量和JVM环境变量
-
ListableBeanFactory: ApplicationContext继承了这个接口,就拥有了获取所有beanNames、判断某个beanName是否存在beanDefinition对象、统计BeanDefinition个数、获取某个类型对应的有beanNames等功能
-
HierarchicalBeanFactory:ApplicationContext继承了这个接口,就拥有了获取父类BeanFactory、判断某个name是否存在bean对象的功能
-
MessageSource:ApplicationContext继承了这个接口,就拥有了国际化功能,比如可以直接利用MessageSource对象获取某个国际化资源(比如不同国家所对应的字符)
-
ApplicationEventPublisher:ApplicationContext继承了这个接口,就拥有了事件发布的功能,可以发布事件,这是ApplicationContext相对于BeanFactory比较突出、常用的功能。
-
ResourcePatternResolver:ApplicationContext继承了这个接口,就拥有了加载并获取资源的功能,这里的资源可以是文件,图片等某个URL资源。
9.BeanPostProcessor是什么
BeanPostProcessor是Spring所提供的一种机制,可以利用该机制对Bean进行定制化加工,在Spring底层源码实现中,也广泛的用到了该机制,BeanPostProcessor通常也叫做Bean后置处理器。
BeanPostProcessor在Spring中是一个接口,我们定义一个后置处理器就是提供一个类实现该接口,在Spring中还存在一些接口继承了BeanPostProcessor,这些子接口是在BeanPostProcessor的基础上增加了一些其它功能。
BeanPostProcessor中的方法:
public interface BeanPostProcessor {
//初始化前方法,表示可以利用这个方法来对Bean在初始化前进行自定义加工
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//初始化后方法,表示可以利用这个方法来对Bean在初始化后进行自定义加工
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
InstantiationAwareBeanPostProcessor中的方法
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
//实例化前
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
//实例化后
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
//属性注入后
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
10.AOP是什么?
AOP是面向切面编程,是一种非常适合在无需修改业务代码的前提下,对某个或某些业务增加统一的功能,比如日志记录、权限控制、事务管理等,能很好的使得代码解耦,提高开发效率
- Advice:Advice可以理解为通知、建议,在Spring中通过定义Advice来定义代理逻辑
- Pointcut:Pointcut是切点,表示Advice对应的代理逻辑应用在哪个类、哪个方法上
- Advisor:等于Advice+pointcut,表示代理逻辑和切点的一个整体,程序员可以通过定义或封装一个Advisor,来定义切点和代理逻辑
- Weaving:表示织入,将Advice代理逻辑在源代码级别嵌入到切点的过程,就叫做织入
- Target:Target表示目标对象,也就是被代理对象,在AOp生成代理对象中会持有目标对象
- Join Point:Join Point表示连接点,在Spring AOP中,就是方法的执行点
AOP的工作原理:
1.Spring生成bean对象时,先实例化出来一个对象,也就是target对象
2.再对target对象进行属性填充
3.在初始化后步骤中,会判断target对象有没有对应的切面
4.如果有切面,就表示当前对象需要进行AOP
5.通过Cglib或JDK动态代理机制生成一个代理对象,作为最终的bean对象
6.代理对象有一个target属性指向了target对象
11.什么是Spring?
Spring是一个生态:可以构建java应用所需要的一切基础设施
通常Spring指的是Spring Framework
核心解释:
- Spring是一个轻量级的开源框架
- Spring是为了解决企业级应用开发的业务逻辑层和其它各层,对象和对象直接耦合的问题
- Spring是一个IOC和AOP的容器框架
- IOC:控制反转
- AOP:面向切面编程
- 容器:包含并管理应用对象的生命周期
12.Spring IOC的实现机制是什么?
简单工厂+反射
13.IOC和DI的区别是什么?
IOC:控制反转思想,解决耦合问题
DI:依赖注入,是实现IOC的一个过程
14.BeanFactory和FactoryBean有什么区别?
BeanFactory是一个工厂,也就是一个容器,是来管理和生产bean的;FactoryBean是一个bean,所以也是由BeanFactory来管理的,不过FactoryBean不是一个普通的Bean,它会表现出工厂模式的样子,BeanFactory里面的getObject()就是用来获取FactoryBean产生的对象,所以在BeanFactory中使用“&”来得到FactoryBean本身,用来区分通过容器获取FactoryBean产生的对象还是获取FactoryBean本身
15.Spring IOC容器的加载过程?
1.实例化一个ApplicationContext对象
2.调用bean工厂后置处理器完成扫描
3.循环解析扫描出来的类信息
4.实例化一个BeanDefinition对象来存储解析出来的信息
5.把实例化好的beanDefinition对象put到beanDefinitionMap当中缓存起来,以便后面实例化bean
6.再次调用其它bean工厂后置处理器
7.当然Spring还会干很多事情,比如国际化,比如注册BeanPostProcessor等等,如果我们只关心如何实例化一个bean的话,那么这一步就是spring调用finishBeanFactoryInitialization方法来实例化单例bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,一次判断这个bean是否是Lazy,是否prototype,是否abstract等等
8.如果验证完成spring在实例化一个bean之前需要推断构造方法,因为spring实例化对象是通过构造方法反射,故而需要知道用哪个构造方法
9.推断完构造方法之后spring调用构造方法反射实例化一个对象;注意是对象,这个时候对象已经实例化出来了,但是并不是一个完整的bean,最简单的体现是这个时候实例化出来的对象属性是没有注入,所以不是一个完整的bean
10.spring处理合并完成后的beanDefinition
11.判断需要是否完成属性注入
12.如果需要完成属性注入,则开始注入属性
13.判断bean的类型回调Aware接口
14.调用生命周期回调方法
15.如果需要代理则完成代理
16.put到单例池-bean完成-存在spring容器中
16.Spring IOC有哪些扩展点?
1.BeanDefinitionRegistryPostProcessor Bean定义后置处理器
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
/**
* IOC加载时注册BeanDefinition时会调用
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setBeanClass(Object.class);
registry.registerBeanDefinition("object",rootBeanDefinition);
}
/**
* 在注册beanDefinition时调用
* @param beanFactory
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
2.加载BeanPostProcessor实现类:在Bean的生命周期会调用9次Bean的后置处理器
3.初始化阶段调用XXXAware接口的SetXXXAware方法
public class MyClass implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {
private BeanFactory beanFactory;
private String beanName;
private ApplicationContext applicationContext;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext =applicationContext;
}
}
4.执行BeanPostProcessor实现类的postProcessorBeforeInitialization方法
5.执行InitializingBean实现类的afterPropertiesSet方法
public class MyClass2 implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
//初始化阶段调用
}
}
6.执行bean的init-method属性指定的初始化方法
public class MyClass2 {
@PostConstruct
public void init(){
//执行bean的init-method属性指定的初始化方法
}
}
7.执行BeanPostProcessor实现类的postProcessAfterInitialization方法
8.初始化完成
9.关闭容器,执行Disposible实现类的destory
10.执行bean的destory-method属性制定的初始化方法
public class MyClass2 {
@PreDestroy
public void destroy(){
}
}
17. 配置Bean有哪几种方式
1.xml
2.@Component(@Controller、@Service、@Repository) 前提需要配置 利用反射调用构造方法
3.javaConfig:@Bean (可以自己控制实例化过程,配合@Configuration)
4.@Imort。//TODO
18.Bean有那几种作用域
singleton:每一个Spring IoC容器都拥有唯一的一个实例对象
prototype:一个Bean定义,任意多个对象
request:一个HTTP请求会产生一个Bean对象,也就是说,每一个HTTP请求都有自己的Bean实例。只在基于web的Spring ApplicationContext中可用
session:限定一个Bean的作用域为HTTPsession的生命周期。同样,只有基于web的Spring ApplicationContext才能使用
application:限定一个Bean的作用域为全局HTTPSession的生命周期。通常用于门户网站场景,同样,只有基于web的Spring ApplicationContext可用
19.Spring的bean是线程安全的吗?
单例bean的不安全的情况:
如果在类中声明成员变量(有状态bean),并且有读写操作,就会线程不安全
Spring如何处理线程并发问题:
- 将bean的作用域变为多例
- 将成员变量放在ThreadLocal
- 方法或者代码块上加上同步锁,影响性能
20.Spring构造方法推断
所有构造方法不加@Autowired注解的情况下:
1.有一个构造方法,直接用该构造方法
2.有多个构造方法,如果多个构造方法中有无参构造方法,用无参构造方法;如果没有无参构造方法,报错
只有一个构造方法加@Autowired注解的情况下,使用该构造方法
有多个构造方法加@Autowired注解的情况下,有无参构造方法用无参构造方法,无无参构造方法报错。