spring(一)
一、 AOP 的实现
以 Java 注解配置实现为列,通过 Import 注解注册一个 Bean 后置处理器,处理 AOP
解析切面:在 bean 创建之前的第一个 bean 后置处理器会去解析切面(解析切面中的通知,切点,也就是相关的注解,每一个通知都会生成一个 advisor)
创建动态代理:一般的类初始化后调用后置处理器 BeanPostProcessor 拿到之前缓存的 advisor,通过 advisor 判断当前 bean 是否被切点匹配,如果匹配,则创建对应的动态代理。
调用:通过之前创建的动态代理调用增强方法,通过调用链模式依次调用通知方法。
二、IOC 的加载过程
主要分为四个形态:IOC 初始化开始时间是在初始化上下文时(new ApplicitonContext() 时)
概念态:在初始化上下文之前,
定义态:通过 bean 工厂的后置处理器(InvokeBeanFactoryProcessors)把 bean 包装为一个 beanDefinition 对象(包含 bena 的各种基本信息)
纯净态(提前暴露实列):相对于是放到缓存中但是还未初始化完成
完成态:已经放入到单例中的实列
三、SptingIOC 的扩展点以及调用时机
1、初始化 BeanDefinitionn 时: 1.1、BeanDefinitionRegistryPostProcessor 在注册 beanDefinition 时可以进行一些修改; 1.2、bean 工厂的后置处理器 2、初始化阶段 初始化阶段调用 XXXAware 接口,重写 setXXXAware 的方法 生命周期回调: BeanPostProcessor 实现类,有初始化方法,销毁 初始化实现方法:注解 @PostConstruct、实现接口 InitializingBean、使用配置类时的 @bean 注解 可以指定 initMethod 对应的方法 销毁:也有对应的方式 3、在所有对象都初始化完成后扩展 首先要确定是什么时候所有的实列初始化完成:初始化开始时 new ApplictionContext()--->refresh() --->finishBeanFactoryInitialization()【在此方法中循环所有的 BeanDefinition 对象,调用 BeanFactory.getBean()进行初始化】循环完成,则所有类初始化完成。 扩展点:1、完成后会调用 SmartInitializingSingleton 接口,所以可以实现 此接口,实现对应的接口,完成扩展 2、 在 refresh()方法的最后会有一个时间发布,所以可以监听对应的事件完成扩展。4、整个容器初始化完成后(springboot): springboot 则可以直接实现 ApplicationRunner 接口
四、spring 事务传播行为的原理
1、解析切面:会在 bean 的第一个后置处理器进行解析 advisor(pointcut 通过 @transacation 注解解析的切点)【advosor 是通过 @EnableTransactionManagement 注解导入的 TransactionManagementConfigurationSelector 注册了一个 ProxyTransactionManagementConfiguration 配置类 ,此配置类注册了 BeanFactoryTransactionAttributeSourceAdvisor 的 advosor】2、生成动态代理:判断类或者是方法上是否有 @Transactional 注解,然后生成动态代理 3、执行:在代理的方法执行前后进行增强(设置自动提交事务为 false,执行完后再提交)
Spring 事务的信息存储在 ThreadLocal 中,所以一个线程只能由一个事务。嵌套事务主要有两类:加入原事务:当传播行为是融入外部事务时,则拿 ThreadLocal 中的 connection,共享一个链接,共同提交,回滚;创建新事务:当传播内部事务的传播行为是创建新事务时,则内部事务先把外部事务暂存起来,完后新建 Connection 链接,当内部事务完成后,再把外部事务信息还原到 ThreadLocal 中。
五、多线程事务可以保证一致性,以及失效的原因
1、Spring 事务是依赖 ThreadLocal 存储 Connection 实现的,所以多线程是无法保证一致性的,解决方案:①编程式事务,②分布式事务的思想 2、失效原因: ①、声明在 pivate 修饰的方法上, ②、内部自己调用事务的方法 ③、自己捕获了异常没有抛出去 内部调用导致事务传播失效 解决方案: ①、 在本类中注入自己的实列 bean 进行调用 ②、设置暴露当前代理对象到本地线程 ,可以使用 AopContext.currentProxy() 拿到当前执行的代理对象
六、事件监听
核心为观察者模式:三大要素, 事件、监听器,事件发布器异步事件:多线程实现,(事件发布器设置一个 executor 线程池对象)
七、单列对象会有有什么问题?怎么解决?
如果有成员变量,则会有线程安全问题,解决方法: 1、把成员变量放入到方法中, 2、如果必须要使用成员变量,则可以使用 ThreadLocal,把成员变量放入到 ThreadLocal 中 3、同步锁
评论