|
| 1 | +### 简单描述bean的生命周期? |
| 2 | + |
| 3 | +> 生命周期流程图 |
| 4 | +
|
| 5 | + |
| 6 | + |
| 7 | +> 通过getBean()方法获取Bean |
| 8 | +
|
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +> 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法 |
| 16 | +
|
| 17 | + |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | +> 实例化对象调用对象的构造函数 |
| 24 | +
|
| 25 | + |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +> 调用 InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法 |
| 32 | +
|
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +> 调用InstantiationAwareBeanPostProcessor的postProcessProperties |
| 38 | +
|
| 39 | + |
| 40 | + |
| 41 | +> 调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues |
| 42 | +
|
| 43 | + |
| 44 | + |
| 45 | +> 设置属性值 |
| 46 | +
|
| 47 | + |
| 48 | + |
| 49 | +> 初始化Bean |
| 50 | +
|
| 51 | + |
| 52 | + |
| 53 | +> 调用Aware接口 |
| 54 | +
|
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | + |
| 59 | +> 调用BeanPostProcessor的postProcessBeforeInitialization方法 |
| 60 | +
|
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | + |
| 65 | +> 调用InitializingBean的afterPropertiesSet方法 |
| 66 | +
|
| 67 | + |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | +> 调用init-method方法 |
| 72 | +
|
| 73 | + |
| 74 | + |
| 75 | +> 调用BeanPostProcessor的postProcessAfterInitialization方法 |
| 76 | +
|
| 77 | + |
| 78 | + |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | + |
| 83 | + |
| 84 | + |
| 85 | + |
| 86 | + |
| 87 | +Spring容器帮助我们去管理对象,从对象的产生到销毁的环节都是由容器进行控制,其中主要包含实例化和初始化两个关键环节,当然在整个过程中会有一些扩展点。下面来详细描述下各个环节和步骤。 |
| 88 | + |
| 89 | +> 1. 实例化bean对象通过反射的方式来生成 |
| 90 | +
|
| 91 | +在源码中有一个createBeanInstance的方法是专门来生成对象的 |
| 92 | + |
| 93 | +> 2. 当bean对象创建完成后,对象的属性值都是默认值,所以需要开始给bean填充属性,通过populateBean方法来完成对象属性的填充,期间会涉及到循环依赖的问题 |
| 94 | +
|
| 95 | +> 3. 向bean对象中设置容器属性,会调用invokeAwareMethods方法来将容器对象设置到具体的bean对象中去 |
| 96 | +
|
| 97 | +如:applicationContext、BeanFactory、Enviroment、ResourceLoader |
| 98 | + |
| 99 | +BeanFactoryAware、ApplicationContextAware |
| 100 | + |
| 101 | +> 4. 调用BeanPostProcessor中的前置处理方法来进行Bean对象的扩展工作,ApplicationContextPostProcessor |
| 102 | +
|
| 103 | +> 5. 调用InvokeinitMethods方法来完成初始化方法的调用,在此方法过程中,需要判断当前bean对象是否实现了initializingBean的接口,如果实现了调用afterPropertiesSet方法来最后设置Bean对象 |
| 104 | +
|
| 105 | +> 6. 调用BeanPostProcessor的后置处理方法,完成对Bean对象的后置处理工作,AOP就是在此处实现的,实现的接口实现名字叫做AbstractAutoProxyCreator |
| 106 | +
|
| 107 | +> 7. 获取到完整对象,通过getBean的方式去进行对象的获取和使用 |
| 108 | +
|
| 109 | +> 8. 当对象使用完成之后,容器在关闭的时候会销毁对象,首先会去判断是否实现了DisposableBean接口,然后去调用destroyMethod方法 |
| 110 | +
|
| 111 | +### BeanFactroy和FactoryBean的区别 |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | +BeanFactory和FactoryBean都可以用来创建对象,只不过创建的流程和方式不同。 |
| 116 | +当使用BeanFactory的时候必须要严格的遵守 Bean 的生命周期,经过一系列繁杂的步骤之后才可以创建单例对象,是流水线式的创建过程。 |
| 117 | +而FactoryBean是用户可以自定义bean对象的创建流程,不需要按照Bean的生命周期来创建,在此接口中包含了三个方法 |
| 118 | +getObject();// 获取对象 |
| 119 | +getObjectType();// 获取对象类型 |
| 120 | +isSingleton();// 判断是否是单例对象 |
| 121 | + |
| 122 | + |
| 123 | + |
| 124 | +如:Mybatis中的SqlSessionFactoryBean |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | +### Spring中使用的设计模式 |
| 129 | + |
| 130 | +> 1. 单例模式 |
| 131 | +
|
| 132 | +Spring 中的bean都是单例的 |
| 133 | + |
| 134 | +> 2. 工厂模式 |
| 135 | +
|
| 136 | +BeanFactroy |
| 137 | + |
| 138 | +> 3. 模板模式 |
| 139 | +
|
| 140 | +postProcessorBeanFatory |
| 141 | + |
| 142 | +onRefresh |
| 143 | + |
| 144 | +> 4. 观察者模式 |
| 145 | +
|
| 146 | +listener,event,multicast |
| 147 | + |
| 148 | +> 5. 适配器模式 |
| 149 | +
|
| 150 | +Adapter |
| 151 | + |
| 152 | +> 6. 装饰者模式 |
| 153 | +
|
| 154 | +BeanWrapper |
| 155 | + |
| 156 | +> 7. 责任链模式 |
| 157 | +
|
| 158 | +使用Aop的时候会有一个责任链模式 |
| 159 | + |
| 160 | +> 8. 代理模式 |
| 161 | +
|
| 162 | +Aop中动态代理 |
| 163 | + |
| 164 | +> 9. 委托者模式 |
| 165 | +
|
| 166 | +delegate |
| 167 | + |
| 168 | +> 10. 建造者模式 |
| 169 | +
|
| 170 | +SpringApplicationBuilder |
| 171 | + |
| 172 | +> 11. 策略模式 |
| 173 | +
|
| 174 | +XmlBeanDefinitonReader、 PropertiesBeanDefinitionReader |
| 175 | + |
| 176 | + |
| 177 | + |
| 178 | +### ApplicationContext和BeanFactroy的区别 |
| 179 | + |
| 180 | +BeanFactory是访问Spring容器的根接口、里面只是提供了某些基本方法的约束和规范,为了满足更多需要,ApplicationContext实现了BeanFactory接口,并在此接口的基础上做了某些扩展功能提供了更加丰富的API |
| 181 | + |
| 182 | + |
| 183 | + |
| 184 | + |
| 185 | + |
| 186 | +### 谈谈你对循环依赖的理解 |
| 187 | + |
| 188 | +> 1. 什么是循环依赖 |
| 189 | +
|
| 190 | +A 依赖 B B 依赖 A |
| 191 | + |
| 192 | + |
| 193 | + |
| 194 | +> 2. Spring中Bean对象的创建都要经历实例化和初始化(属性填充.)的过程 |
| 195 | +
|
| 196 | + |
| 197 | + |
| 198 | + |
| 199 | + |
| 200 | +> 3. 只有一级缓存是否可行? 不可以 |
| 201 | +
|
| 202 | +会把成品状态的Bean 对象和半成品状态的Bean对象放到一起,而半成品对象是无法暴露给外部使用的,所以要将成品和半成品分开存储,一级缓存()中放置成品对象,二级缓存()放置半成品对象 |
| 203 | + |
| 204 | +> 4. 只有二级缓存是否可行? 不可以 |
| 205 | +
|
| 206 | +如果整个应用程序中不涉及到AOP,那么二级缓存是足以解决循环依赖的问题,如果AOP中存在了循环依赖,那么必须要用三级缓存才能解决 |
| 207 | + |
| 208 | +> 5. 为什么需要三级缓存 |
| 209 | +
|
| 210 | + |
| 211 | + |
| 212 | +三级缓存的Value类型是ObjectFactroy,是一个函数式接口,不是直接进行调用,只有在调用getObject方法的时候才会去调用里面存储的lamda表达式,存在的意义是保证在整个容器运行过程中同名的bean对象只能有一个 |
| 213 | + |
| 214 | +> 如果一个对象被代理,或者说需要生成代理对象,那么是否需要先生成一个原始对象?要的 |
| 215 | +
|
| 216 | +> 当创建出代理对象之后,会同时存在代理对象和普通对象,那么此时我该用哪一个? |
| 217 | +
|
| 218 | +当需要代理对象的时候,或者说代理对象生成的时候必须要覆盖原始对象,也就是说,整个容器中一个bean名称仅有一个bean |
| 219 | + |
| 220 | +在实际调用的过程中,是没有办法确定什么时候对象需要被调用,因此当一个对象被调用的时候,优先判断当前对象是否需要被代理,类似于回调机制,当获取对象之后根据传入的lamda表达式来确认返回的是哪一个确定的对象 |
| 221 | + |
| 222 | +如果条件符合返回代理对象、如果条件不符合返回原始对象 |
| 223 | + |
| 224 | + |
| 225 | + |
| 226 | + |
| 227 | + |
| 228 | + |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | +### Spring Aop 底层实现 |
| 233 | + |
| 234 | +动态代理 |
| 235 | + |
| 236 | +aop是ioc的一个扩展功能,先有的ioc,在有的aop,只是在ioc的整个流程中新增的一个扩展点而已:BeanPostProcessor: |
| 237 | + |
| 238 | +bean的创建过程中有一个步骤可以对bean进行扩展实现,aop本身就是一个扩展功能,所以在BeanPostProcessor的后置处理方法中来实现 |
| 239 | + |
| 240 | +> 1. 代理对象的创建过程(advice,切面,切点) |
| 241 | +
|
| 242 | +> 2. 通过JDK或者CGlib的方式来生成代理对象 |
| 243 | +
|
| 244 | +> 3. 在执行方法调用的时候,会调用到生成的字节码文件中,直接会找到 DynamicAdvisoredInterceptor类中的intercept方法,从此方法开始执行 |
| 245 | +
|
| 246 | +> 4. 根据之前定义好的通知来生成拦截器链 |
| 247 | +
|
| 248 | +> 5. 从拦截器链中依次获取每一个通知开始进行执行,在执行过程中,为了方便找到下一个通知是哪个,会有一个CglibMethodInvocation的对象,找的时候是从-1的位置依次开始查找并执行的 |
| 249 | +
|
| 250 | + |
| 251 | + |
| 252 | +### Spring的事务是如何回滚的 |
| 253 | + |
| 254 | +Spring的事务管理是如何实现的? |
| 255 | + |
| 256 | +总:spring的事务是由aop来实现的,首先要生成具体的代理对象,然后按照aop整套流程来执行具体的操作逻辑,正常情况下要通过通知来完成核心功能,但是事务不是通过通知来实现的,而是通过一个TransactionInterceptor来实现的,然后调用invoke来实现具体的逻辑 |
| 257 | + |
| 258 | +分: |
| 259 | + |
| 260 | +> 1. 先做准备工作,解析各个方法上事务相关的属性,根据具体的属性来判断是否开启新事务 |
| 261 | +
|
| 262 | +> 2. 当需要开启的时候,获取数据库连接,关闭自动提交功能,开启事务 |
| 263 | +
|
| 264 | +> 3. 执行具体的Sql逻辑操作 |
| 265 | +
|
| 266 | +> 4. 在操作过程中如果执行失败了,那么会通过completTransactionAfterThrowing来完成事务的回滚操作,回滚的具体逻辑是通过doRollBack方法来实现的,实现的时候也是先获取连接对象 |
| 267 | +
|
| 268 | +> 5. 如果执行正常,则通过commitTransactionAfterReturning来提交事务,提交的具体逻辑是通过doCommit方法来实现的 |
| 269 | +
|
| 270 | +> 6. 当事务执行完毕后需要清除相关的事务信息cleanupTransactionInfo,如果更细致的话需要知道TransactionInfo,TransactionStatus |
| 271 | +
|
| 272 | + |
| 273 | + |
| 274 | + |
| 275 | + |
| 276 | +### Spring事务传播机制 |
| 277 | + |
| 278 | + |
| 279 | + |
| 280 | +> Required:当前有事务则加入,没事务则新建 |
| 281 | +
|
| 282 | +> Supports:当前有事务则加入,没事务则不通过事务 |
| 283 | +
|
| 284 | +> Mandatory:当前有事务则加入,没事务抛异常 |
| 285 | +
|
| 286 | +> Requires_New:新建一个事务 |
| 287 | +
|
| 288 | +> Not_Support:不通过事务的方式运行 |
| 289 | +
|
| 290 | +> Never:不通过事务的方式运行,当前有事务则抛异常 |
| 291 | +
|
| 292 | +> Nested: |
| 293 | +
|
| 294 | +某一个事务嵌套另一个事务的时候怎么办? |
| 295 | + |
| 296 | +A 方法调用 B 方法 AB都有事务,但传播特性不同,那么如果A有异常 B 怎么办,B有异常A怎么办 |
| 297 | + |
| 298 | +总:事务的船舶特性指的是不同方法的嵌套调用过程中,事务应该如何进行处理,是用同一个事务还是不同的事务,当出现异常的时候是回滚还是提交,两个方法之间的相关影响,在日常工作中 使用的比较多的是Required、Require_New, Nested |
| 299 | + |
| 300 | +分: |
| 301 | + |
| 302 | +1. 先说事务的不同分类,可以分为三类:支持当前事务,不支持当前事务,嵌套事务 |
| 303 | +2. 如果外层方法是Required 内层方法是 Required、Require_New, Nested |
| 304 | +3. 如果外层方法是Require_New 内层方法是 Required、Require_New, Nested |
| 305 | +4. 如果外层方法是Nested内层方法是 Required、Require_New, Nested |
| 306 | + |
| 307 | + |
| 308 | + |
| 309 | + |
| 310 | + |
0 commit comments