使用最广泛的Web应用框架
模块
IoC
AOP
- 静态代理:实现类
- 动态代理:
- JDK:实现接口,java反射机制生成一个代理接口的匿名类,调用具体方法的时候调用invokeHandler
- CGLib:ASM字节码编辑技术动态创建类,基于ClassLoad装载,修改字节码生成子类去处理
Bean
- 注解
- 生命周期(扫描类invokeBeanFactoryPostProcessors、封装beanDefinition对象各种信息、放到map、遍历map、验证能否实例化/是否单例/是否factory bean/单例池ConcorrentHashMap/正在创建的容器)、得到class、推断构造方法[根据注入模型/默认]、得到构造方法、反射实例化对象、后置处理器合并beanDefinition、判断是否允许循环依赖、提前暴露bean工厂对象、填充属性自动注入、执行部分aware接口、继续执行部分aware接口生命周期回调方法、完成代理AOP、beanPostprocessor的前置方法、实例化为bean、放到单例池、销毁)
作用域(单例singleton、多例prototype、Request、Session)
循环依赖
情况:属性注入可以破解、构造器不行(三级缓存没自己,因为二级之后去加载B了)
- 三级缓存:去单例池拿、判断是不是正在被创建的、判断是否支持循环依赖、二级缓存放到三级缓存、干掉二级缓存gc、下次直接从三级拿
缓存存放:一级-单例bean、二级-工厂产生bean、三级-半成品
父子容器
事务实现原理
采用不同的连接器
- 用AOP新建立了一个链接(共享链接)
- ThreadLocal当前事务
-
事务传播行为
REQUIRED:如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务
- SUPPORTS:当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
- MANDATORY:当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常
- REQUIRES_NEW:创建一个新事务,如果存在当前事务,则挂起该事务
- NOT_SUPPORTED:始终以非事务方式执行,如果当前存在事务,则挂起当前事务
- NEVER:不使用事务,如果当前事务存在,则抛出异常
NESTED:如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作一样(开启一个事务)
设计模式
单例
- 工厂
- 适配器:根据不同商家适配
- 责任链:继承process链路执行
refresh() 方法中调用的每个方法
- this.prepareRefresh() 激活开启容器
- this.obtainFreshBeanFactory() 获取 bean 工厂
- this.prepareBeanFactory(beanFactory) 对获取到的 beanFactory 做预处理设置
- this.postProcessBeanFactory(beanFactory); beanFactory准备工作完成后进行的后置处理工作
- this.invokeBeanFactoryPostProcessors(beanFactory) 执行 beanFactory 后置处理器的方法
- this.registerBeanPostProcessors(beanFactory) 注册 bean 的后置处理器
- this.initMessageSource() 初始化 MessageSource 组件
- this.initApplicationEventMulticaster() 初始化事件派发器,多播器
- this.onRefresh() 用来初始化子容器中的bean,默认是空方法
- this.registerListeners() 注册监听器
- this.finishBeanFactoryInitialization(beanFactory) 初始化所有剩下的单实例 bean
- this.finishRefresh() 完成ben的创建初始化工作,完成 IOC 容器的创建
使用
AnnotationConfigApplicationContext
ClassPathXmlApplicationContext
getBean整体过程
扫描(找到目录—>获取所有class—>对单例非懒加载类构造BeanDefination和beanDefinationMap)和beanPostProcessorList—>遍历map创建单例bean(创建(推断构造方法—>依赖注入—>用BeanPostProcessor实现aware接口,比如BeanNameAware—>用BeanPostProcessor实现前初始化—>InitializingBean—>用BeanPostProcessor实现AOP)—>存入SingletonObjects 单例池) Bean的创建生命周期
XXX.class—>无参构造方法(推断构造方法)—>普通对象—>依赖注入(autowired属性赋值)—>实现aware接口—>初始化前(@PostConstruct)—>初始化(implements —>初始化(implements ) InitializingBean)—>[初始化后(AOP)—>代理对象]—>Bean
多个构造方法尝试找无参构造方法,有的话就调用,没有就会报错,只有一个构造方法就没事
依赖注入时从IoC容器 Map找
先按照类型去找1个直接用,不管名字
如果有多个(覆盖@Bean会覆盖@Component/不覆盖),再按照名称去找Bean的销毁生命周期
AOP
XXXProxy—>代理对象—>代理对象.target=普通对象—>调用方法test()—>执行@Before切面逻辑—>调用target.test()
代理对象的属性是空的,调用方法就有属性值了
CGLib底层继承(父子类)怎么知道是否要AOP切面?
是一种特殊的bean(@Aspect/@Component)
找出所有的切面Bean—>遍历切面Bean—>遍历每个切面bean方法—>表达式是否匹配—>匹配则需要AOP—>匹配的所有方法缓存起来map供执行的时候用事务
@Transaction
也是生成代理对象,代理类的方法里{1.检查是否有@Transaction标注 2.事务管理器dataSource(A)创建一个数据库连接conn 3.conn.autocommit=false 4. target.test() 用dataSource(B)执行sql1 sql2 5.conn.commit()/conn.rollback()}
不加@Configuration,会造成两个不同的dataSource(A!=B),导致事务失效,@Configuration代理对象(先看容器中有没有dataSource的bean,有直接返回)
懒加载的单例bean
加上@Lazy注解第一次get的时候创建,默认非懒加载的单例bean
@Scope(“prototype”) 原型bean每次get的时候创建(多例)
扫描路径
事务如何传播的?
事务失效是因为代理对象持有的普通对象方法调用的事务方法,代理类去调用才有用,自己注入自己即可
@Transaction(propagation = Propagation.NEVER)
NEVER:以非事务的方式运行,存在一个事务则抛异常
