Spring面试题
1、Spring bean的几种定义方式
1)声明式:基于XML的方式
<bean id="user" class="com.test.User"/>
2)声明式:基于@Component注解
@Component public class User {}
3)声明式:基于@Bean注解
@Component public class Config { @Bean public User user() { return new User(); } }
4)编程式:通过BeanDefinition注册bean信息
public class Test{ public static void main (String[] args) { DefaultListableBeanFactory context = new DefaultListableBeanFactory(); //构造bean定义 BeanDefinition bd = new GenericBeanDefinition(); gbd.setBeanClass(User.class); context.registerBeanDefinition("user", bd); User user = context.getBean(User.class); } }
5)使用FactoryBean创建实例
public class Test implements FactoryBean<User> { public Color getObject() throws Exception { return new User(); } public Class<?> getObjectType() { return User.class; } public boolean isSingleton() { return true; } }
2、Spring bean的生命周期
Spring Bean的生命周期有四大步骤:实例化 -> 属性赋值 ->初始化 ->销毁
1、实例化前后是InstantiationAwareBeanPostProcessor的before和after方法
2、属性赋值后会执行各种Aware接口、InitializingBean的afterPropertiesSet和自定义的init-method
3、初始化前后是BeanPostProcessor的before和after方法(这里 的before方法是在Aware接口后面执行)
4、销毁时执行Disposable的destroy方法和自定义的destroy-method方法
生命周期中主要的接口和方法:
(1) Bean级别的接口
Bean类中定义的方法或者实现了接口的方法,即init-method和destroy-method指定的方法,还有实现了BeanNameAware,BeanFactoryAware,InitializingBean,DiposableBean等接口的方法。
(2) 容器全局后处理器接口
包括了BeanFactoryPostProcessor,InstantiationAwareBeanPostProcessor,BeanPostProcessor这两个接口,它们是容器全局级别的接口。
3、Spring bean的循环依赖
循环依赖:A 依赖 B,B 依赖 A
Spring的单例对象的初始化主要分为三步:
一级缓存 singletonObjects:存放已初始化完毕的bean对象
二级缓存 earlySingletonObjects :存放bean的代理对象(如不需要代理,则直接存放原始对象)
三级缓存 singletonFactories :存放通过构造器实例出来的原始对象
@Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 从一级缓存缓存加载bean Object singletonObject = this.singletonObjects.get(beanName); // 缓存中的bean为空,且当前bean正在创建(说明存在循环引用) if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 加锁 synchronized (this.singletonObjects) { // 从二级缓存中获取(如果二级缓存获取到直接返回) singletonObject = this.earlySingletonObjects.get(beanName); // 缓存中中没有,且允许提前创建(allowEarlyReference说明需要AOP代理,需提前创建好代理对象放到二级缓存中) if (singletonObject == null && allowEarlyReference) { // 从三级缓存中获取对应的ObjectFactory(从三级缓存中获取原始对象作为代理对象的target) ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { //从单例工厂中获取bean singletonObject = singletonFactory.getObject(); // 添加到二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); // 从三级缓存中删除 this.singletonFactories.remove(beanName); } } } } return singletonObject; }
参考:https://www.cnblogs.com/weiqihome/p/12359641.html
作者:月伴飞鱼
链接:https://www.zhihu.com/question/276741767/answer/1192059681
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。