部分书中代码实现

事务部分

1. TransactionTemplate使用Connection怎么获取datasource的连接

如果使用最原生的import java.sql.Connection、datasource,在重写TransactionCallbackWithoutResult()的doInTransaction方法的时候需要通过DataSourceUtils.getConnection(dataSource)来获取连接,而不能直接datasource.getConnection()。主要是DataSourceUtils是从TransactionSynchronizationManager中获取的连接,而datasource.getConnection()是新建一个连接。transactionTemplate.execute()方法中会先进行transactionManager.getTransaction(),在这个方法里面会进行绑定TransactionSynchronizationManager。然后然后再调用doInTransaction方法,也就是复写的方法,然后绑定之后就可以通过DataSourceUtils.getConnection(dataSource)来获取。

2. TransactionSynchronizationManager是啥

里面包含了一堆ThreadLocal,包含这个线程下面的连接的一些信息,包括Transactional resources(datasource)、Transaction synchronizations、Current transaction name、Current transaction read-only status、Current transaction isolation level、Actual transaction active。里面提供了绑定数据源,解绑等操作。

3. 使用TransactionFacade将业务与事务管理相关代码抽象

TransactionFacade属于一个外观模式。如,A类有一个方法A(methodA),B类有一个方法B(methodB)。然后创建一个facade类,包含属性A,B,提供方法domethodA()其中调用A方法、domethodB()其中调用B方法。引用到这里就是使用一个TransactionFacade,里面提供两个方法,一个采用事务的方法txService()方法开始时候开始一个事务,业务代码结束之后提交事务;一个采用非事务方式,直接调用业务代码。示意图如下:

4. @Transaction原理

如果使用注释@Transaction,用于分离事务管理代码和业务代码(例子可以看使用TransactionTemplate进行事务管理例子),业务管理代码去获取有@Transaction注释的method,然后创建要给TransactionTemplate,根据@Transaction的属性设置去设置这个TransactionTemplate,最后调用transactionTemplate.execute(),在execute中调用业务代码。

IOC部分

1. 关于Component注入时候的bean名称问题

根据java.beans.Introspector.decapitalize中的命名规则,注入的bean如果开头两个是大写,就返回原类目,不然就把开头字母变小写,具体代码如下。这就是为什么@Component写在类NewsProvider上面时候不能直接用.getBean("NewsProvider")获取的原因。当然也可以加别名@Component("NewsProvider")。至于原书上面,他的类名是FXNewsProvider开头两个字母是大写,自然没有这个问题。

public static String decapitalize(String name) {if (name == null || name.length() == 0) {return name;}if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&Character.isUpperCase(name.charAt(0))){return name;}char chars[] = name.toCharArray();chars[0] = Character.toLowerCase(chars[0]);return new String(chars);
}

2. 为什么注册的过程可以将BeanDefinition注册到BeanFactory后再配置依赖等。

因为注册的过程中只是将BeanDefinition放到BeanFactory的beanDefinitionMap中而真正初始化是在getBean()的时候,这也就是为什么BeanFactory默认是懒加载机制。而如果在配置依赖之前,就getBean()也就无法初始化Bean。

3. depends-on的疑惑

为什么不加depends-on就不会实例化那个依赖的对象。因为就像2所说的用xml只是注册绑定bean并没有真正的实例化bean,所以如果没有depends-on,也就不会实例化了。

4. 使用org.springframework.beans.factory.config.CustomEditorConfigurer来自定义propertyEditer

spring高版本中,将传入的map从原本的<Class,?>改为了<Class,Class<? extends PropertyEditor>>也就是说原本的value是先实例化后的,现在无法实例化了,因为我的PropertyEditor实现类没有无参构造函数。所以这个方法不可行。需要采用实现PropertyEditorRegistrar类的方式,override的registerCustomEditors这个函数入参提供的方法存在Class,PropertyEditor形式可以直接实例化自定义的propertyEditer
代码可以看重写propertyediter部分和registrar部分、配置bean的xml,其中包括了CustomEditorConfigurer的配置、具体实现在测试在main里面

5.bean的加载过程

主要分为两个阶段,容器启动阶段和实例化阶段。

  1. 容器启动阶段主要是加载Configuration MetaData。通过各种BeanDefinitionReader类来将xml文件映射BeanDefinition,里面包含了类的所有信息,但是不包括类的实例。容器启动最后可以附加一步BeanFactoryPostProcessor,可以将读完的BeanDefinition中的某一些信息进行修改,也就是上面第四点的内容,通常情况下,用于读取.yml中的配置信息,比如一个springboot的项目,启动的时候如果没有.yml就会加载默认的,如果有了的话就覆盖默认的值。
  2. 实例化阶段:下图为BeanFactory中的实例化过程。
    1. 实例化bean,实例化bean主要是根据BeanDefintion中的信息,结合CglibSubclassingInstantiationStrategy以及不同的bean定义类型,返回BeanWrapper类型,然后通过这个beanwrapper设置属性,类似于下面的代码。
    BeanWrapper newsProvider = new BeanWrapperImpl(provider);
    newsProvider.setPropertyValue("newsListener", listener);
    newsProvider.setPropertyValue("newPersistener", persister);
    
    1. 容器检查Aware接口,同时对于依赖的对象进行实例化。实现Aware接口的类,可以将一些信息放到bean里面,例如:BeanNameAware就可以把类名放到这个bean里面、ApplicationContextAware可以把实现这个Bean的ApplicationContext引用放到里面。
    2. BeanPostProcessor会处理满足要求的实例化后的对象。两个方法前一个就是在Initialization之前执行,后一个在之后,前一个主要用于上一个所说的Aware实现类的修改,或者生成代理对象。如果需要自定义,我们只需要实现BeanPostProcessor类,override它的postProcessBeforeInitialization方法,然后对指定的类进行修改就好了,具体实现可以看PasswordDecodePostProcessor
    public interface BeanPostProcessor {Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    }
    
    1. InitializingBean,在上一步结束后检测当前对象是否实现了InitializingBean,如果是就会调用对象的afterPropertiesSet方法,这个主要是用于一些初始化的操作,比如一个类,有init()方法或者初始化一些默认值的方法,就可以实现InitializingBean,并在里面调用init()方法。applicationcontext可以使用init-method在xml中配置初始化方法。
    2. DisposableBean,然后查看是否实现了DisposableBean,如果实现了,就会为该实例注册一个用于对象销毁的回调(callback),也就是在销毁之前先执行这个逻辑。applicationcontext可以使用destroy-method在xml中配置初始化方法。可以用于数据库关闭连接等。在getBean()中只是把这个类注册到disposableBeans中(一个map),如果要摧毁这个bean,还是需要在程序中((ConfigurableListableBeanFactory)container).destroySingletons();

6. AbstractApplicationContext和ResourceLoader之间的关系

AbstractApplicationContext自身继承了实现了DefaultResourceLoader和ResourcePatternResolver。具体继承实现关系如下图。
同时自身有一个PathMatchingResourcePatternResolver类型的变量,在初始化ResourcePatternResolver的时候因为自身继承了ResourceLoader,会将自身作为参数添加到ResourcePatternResolver中,所以当调用getResources的时候,其实就是调用一个以DefaultResourceLoader(AbstractApplicationContext继承这个)为参数的PathMatchingResourcePatternResolver的getResources方法。

7.Reource里面包含了什么,以及和recourceloader之间的关系

包含了这个文件的信息。包括文件名,file,inputStream,Description,URL。
recourceloader接口中有一个getResource,不同的实现类不同,也就是根据传进来的路径创建一个resource并返回。DefaultResourceLoader中并没有resource属性。

8. 基于注解方式的注入里面都做了什么

根据书中的思路来,首先,当我们给一个类加入@Autowire之后,就可以自动绑定依赖,而这个依赖就需要在xml文件中声明<bean></bean>,同时,容器需要去读取这个bean,就像之前的bean实例化的时候,在实例化bean,并且设置了对象之后,可以使用BeanPostProccessor来重新设置它的field,而spring提供了AutowiredAnnotationBeanPostProcessor实现,来作为读取Autowire的bean,那么我们只需要在xml中添加<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>即可。然后为了简化这两个东西的配置,我们可以通过<context:annotation-config/>配置来同时把AutowiredAnnotationBeanPostProcessor 和CommonAnnotationBeanPostProcessor注册到容器,同时还会把PersistenceAnnotationBeanPostProcessor和RequiredAnnotationBeanPostProcessor一并进行注册。但是还是需要在这个xml里面配置最基础的<bean id="" class=""></bean>,为了再次简化,我们可以在需要初始化的bean类上面添加@Component加上之后设置扫描路径,扫描指定路径下面的包,如果带有这个@Component就会提取该类的相关信息,构建对应的BeanDefinition,然后把构建完的BeanDefinition注册到容器。classpath-scanning功能的触发是由<context:component-scan>决定的<context:component-scan base-package="..."/>可以使用这种方式来设置路径,当然这个方法中也会注册各种BeanPostProcessor包。

AOP部分

1. 当ProxyFactory作为weaver的时候,为什么需要使用接口类作为代理对象?

IRequestable proxyObject=(IRequestable)weaver.getProxy();
SpringAop在使用代理模式实现代理对象的时候,一般采用动态代理和CGLIB,分别对实现某个接口的类和没有任何接口的目标类进行代理。如果一个类实现了某个接口,那么这个类就会默认采用动态代理的方式,所以返回的也是一个接口的实现类,因此就需要使用接口类作为代理对象,而没有实现任何类型的就会默认采用CGLIB的方式。

书中解释,在代理对象的场景中,接口的具体实现类和这个具体实现类的代理对象是两个不同的对象,我们可以将接口实现类和它的代理对象都强制转化为接口类型,而无法将代理对象类型强制转化为接口实现类类型。如动态代理示例

当然可以通过weaver.setProxyTargetClass(true)将有实现某个接口的类通过CGLIB生成代理对象。

2. ProxyFactory内部的构造

ProxyFactory继承了ProxyCreatorSupport,提供getProxy()方法,getProxy()调用了ProxyCreatorSupport中的createAopProxy(),ProxyCreatorSupport包含属性AopProxyFactory,这个属性是创建Proxy的工厂类,DefaultAopProxyFactory是它的实现,调用AopProxyFactory的createAopProxy方法后,最后根据目标类的类型获得JdkDynamicAopProxy(动态代理)或ObjenesisCglibAopProxy(CGLIB)

《Spring 揭秘》读书笔记相关推荐

  1. 读书笔记 | 墨菲定律

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  2. 读书笔记 | 墨菲定律(一)

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  3. 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记

    <洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...

  4. 股神大家了解多少?深度剖析股神巴菲特

    股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...

  5. 2014巴菲特股东大会及巴菲特创业分享

     沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...

  6. 《成为沃伦·巴菲特》笔记与感想

    本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...

  7. 读书笔记002:托尼.巴赞之快速阅读

    读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...

  8. 读书笔记001:托尼.巴赞之开动大脑

    读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...

  9. 读书笔记003:托尼.巴赞之思维导图

    读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...

  10. 产品读书《滚雪球:巴菲特和他的财富人生》

    作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...

最新文章

  1. vs中将网站aspx.cs文件打包成一个dll
  2. 二分法细节学习-mid
  3. Spring5源码 - 05 invokeBeanFactoryPostProcessors 源码解读_2
  4. 天玥运维安全网关默认密码_Soul网关发布全新架构V2.2.0,让高性能网关变得如此简单
  5. java plat停止_击按钮就停止运行,大牛帮我看看
  6. P2468 [SDOI2010]粟粟的书架 主席树 + 二分 + 二维前缀和
  7. python词云改颜色_一种用Python生成词云
  8. OSG仿真案例(5)——创建火光、爆炸(碎片)
  9. day3-python的基础类源码解析——collection类
  10. 如何使用python处理nc数据制作Mike风场文件--以ERA5数据为例
  11. 7-79 约分最简分式
  12. linux gz he xz,gz与xz两种压缩格式的对比
  13. 全网超火的情感文案号视频是怎么制作的?
  14. python (win32com) 批量删除 word (docx, doc) 中所有页眉、页脚 (Word.Application, Word.Basic)
  15. 匈牙利为庆贺第17届奥运会而发行的纪念邮票
  16. 【罗开传奇】传奇服务端调整人物属性脚本命令ChangeHumAbility
  17. 怎样防止苹果系统更新_苹果xs换过原装屏幕可以更新14系统吗?
  18. 汉诺塔(C语言实现)
  19. 美容院管理系统统一管理制度?
  20. 关于Cron表达式中的周一至周五正确的配置

热门文章

  1. 11款超5000星 后台管理模板, 总有一款适合你!
  2. 电源大师课笔记 1.3
  3. c语言人物游戏代码大全,(c语言)游戏中由人物各种信息组成的结构体
  4. Java学到什么程度可以面试工作?
  5. UI设计素材干货,字体设计灵感酷站
  6. IDEA中导入Mysql驱动包
  7. 利用模板导出文件(一)之XLSTransformer导出excel文件
  8. delphi2010转码Base64图片上传百度AI接口识别发票手记
  9. delphi下载网站文件(支持https协议)
  10. 心语家园系统维护工具箱v1.0