这些知识整理都是自己查阅帅丙资料(当然还有其他渠道)加以总结滴~ 每周都会更新知识进去。
如有不全或错误还请大家在评论中指出~
策略模式:抽象了出了接口,将业务逻辑封装成一个一个的实现类,任意地替换。利用java8的Map与函数式接口来实现。
进入createBean方法,如果有代理方法(AOP)则调用postProcessBeforeInstantiation,换原本的Bean作为代理。进入doCreateBean方法,调用createBeanInstance
创建bean实例。(这里判断了Spring的循环依赖问题)
这时进入populateBean
方法,调用postProcessAfterInstantiation方法,如果调用返回false,表示不必继续进行依赖注入,直接返回。如果返回true,向 bean 的成员变量注入自定义的信息。最后通过BeanWrapper提供的设置属性的接口完成属性依赖注入(DI)。
下一步进入initializeBean
(),首先判断是否实现了Aware接口,有的话就注入相关属性。接着调用初始化的前置(BeanPostProcessor)操作,接着执行初始化的方法,最后调用bean初始化的后置(BeanPostProcessor)操作。
注册Bean的销毁
逻辑。当Bean不再需要时,销毁Bean。
InstantiationAwareBeanPostProcessor作用于实例化阶段的前后。
createBeanInstance()
postProcessBeforeInstantiation在doCreateBean之前调用
,该方法的返回值会替换原本的Bean作为代理
,这也是Aop等功能实现的关键点。Spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法
(我的策略模式就是这么干的),或者在配置文件中通过init-method
指定,两种方式可以同时使用。
populateBean()
BeanPostProcessor作用于初始化阶段的前后,它也会注册为Bean
初始化 initializeBean()
注入Aware接口+自定义的处理 (所有的Aware方法都是在初始化阶段之前调用的)
销毁 容器关闭时调用
// 忽略了无关代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//bean实例包装类
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
//创建bean的时候,这里创建bean的实例有三种方法
//1.工厂方法创建
//2.构造方法的方式注入
//3.无参构造方法注入
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充bean实例的属性
populateBean(beanName, mbd, instanceWrapper);
//初始化bean,过程如下:
//1:判断是否实现了BeanNameAware,BeanClassLoaderAware,
// BeanFactoryAware方法,如果有,则设置相关的属性
//2: 调用bean初始化的前置(BeanPostProcessor)操作
//3: 执行初始化的方法。
// 如果有initializingBean,则调用afterPropertiesSet
// 如果有InitMethod,则调用初始方法
//4: 调用bean初始化的后置(BeanPostProcessor)操作
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
BeanPostProcessor
(SentinelBeanPostProcessor)InstantiationAwareBeanPostProcessor
Aop等功能实现的关键点
。执行顺序
BeanPostProcessor有很多个,而且每个BeanPostProcessor都影响多个Bean,其执行顺序至关重要,必须能够控制其执行顺序才行。
1 PriorityOrdered是一等公民,首先被执行,PriorityOrdered公民之间通过接口返回值排序
2 Ordered是二等公民,然后执行,Ordered公民之间通过接口返回值排序
3 都没有实现是三等公民,最后执行
第二大类:只调用一次的接口
Aware Group1
1 BeanNameAware
2 BeanClassLoaderAware
3 BeanFactoryAware
Aware Group2
1 EnvironmentAware
2 EmbeddedValueResolverAware 这个知道的人可能不多,实现该接口能够获取Spring EL解析器,用户的自定义注解需要支持spel表达式的时候可以使用,非常方便。
3 ApplicationContextAware
scope=singleton(默认,单例,生成一个实例) 不是线程安全,性能高
scope=prototype(原型多线程, 生成多个实例)
addsingletonFactory属性没被注入,populateBean方法是用来赋值的
)getSingleton()
方法, 判断到三级缓存singletonFactories中存在A
(单例工厂实例),就调用单例工厂的getObject方法返回对象实例
;将实例A放入二级缓存
;从三级缓存中移除
A。B实例放入一级缓存,并清空其它级缓存。
彻底完成B的创建,返回给A一级缓存singletonObjects(ConcurrentHashMap):用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
二级缓存earlySingletonObjects(HashMap):提前曝光的单例对象的cache,存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
三级缓存singletonFactories(HashMap):单例对象工厂的cache,存放 bean 工厂对象,用于解决循环依赖
作用域 | 描述 |
---|---|
singleton | 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。 |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。 |
application | 限定一个Bean的作用域为ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。 |
Spring和SpringMVC的容器具有父子关系,Spring容器为父容器,SpringMVC为子容器,子容器可以引用父容器中的Bean,而父容器不可以引用子容器中的Bean
。(例子:ssm框架,spring可以管理service,mapper,springmvc管理controller,mybatis编写mapper,controller就需要调用service,service调用mapper,因为springmvc容器是spring的子容器,可以通过父容器找到service和mapper,但是在service中却是找不到controller的。保证一种资源的局部性
。)
Spring支持编程式
事务管理以及声明式
(基于AOP)事务管理两种方式。
事务的传播性:
@Transactional(propagation=Propagation.REQUIRED)
事务的隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读,
不可重复读) 基本不使用
只读: (一次执行多条查询语句,也需要回滚)
@Transactional(readOnly=true)
该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。
事务的超时性:
@Transactional(timeout=30)
回滚:
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class,
Exception.class})
一个新的事务应该被启动还是被挂起
,或者是一个方法是否应该在事务性上下文中运行
PROPAGATION_REQUIRED (默认)
PROPAGATION_NOT_SUPPORT(只读的时候在设置个ReadOnly)
非 public 修饰
的方法上同一个类中方法调用
,导致@Transactional失效异常被自己catch
了父子上下文重叠
。Spring 解决了关键的问题:将对象之间的关系转而用配置管理
静态代理:实现类
动态代理:
JDK动态代理
(实现接口),java反射机制生成一个代理接口的匿名类,调用具体方法的时候调用invokeHandler通过bind方法建立代理与真实对象关系,通过Proxy.newProxyInstance(target)生成代理对象。
代理对象通过反射invoke方法实现调用真实对象的方法
CGLIB
(asm字节码编辑技术创建类,基于classLoad装载,修改字节码生成子类处理)proxy类
获得有关方法和InvocationHandler构造方法传参。但java不能同时继承两个类
,我们需要和想要代理的类建立联系,只能实现一个接口要获取原类,只能继承/实现
,或者就是那个代理类接口反射出对我有用
的东西。静态代理: 程序运行前就已存在的编译好的代理类。实现步骤:
1、定义业务接口。
2、实现业务接口。
3、定义代理类并实现业务接口,最后通过客户端调用。
动态代理:程序运行期间根据需要动态创建代理类及其实例已完成功能
BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
BeanFactory:
是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
ApplicationContext:
应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;
ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;
SpringBoot的自动装配原理,其实就是在项目启动的时候去加载META-INF下的spring.factories文件。
spring.factories
可以找到自动配置类的路径,但是不是所有存在于spring,factories中的配置都进行加载,而是通过@ConditionalOnClass
注解进行判断条件是否成立(只要导入相应的stater
,条件就能成立),如果条件成立则加载配置类,否则不加载该配置类。none, servlet, reactive
响应式非阻塞)需要初始化的类进行实例化添加到一个集合中等待备用
ApplicationListener.class
,而初始化应用上下文传入的参数是ApplicationContextInitializer.class
。在SpringBoot中启动tomcat的工作在刷新应用上下文上下这一步。而tomcat的启动主要是实例化两个组件:Connector、Container,一个tomcat实例就是一个Server,一个Server包含多个Service,也就是多个应用程序,每个Service包含多个Connector和一个Container,而一个Container下又包含多个子容器。