在阿里P8承认Spring为面试重点后,这本笔记在程序员的手中就是“香饽饽”了
Spring框架是一个分层架构,它包含一系列的功能要素,并被分为大约20个模块,如这些模块被总结为以下几部分:
Core Container
Core Container (核心容器)包含有Core、Beans、 Context 和Expression Language模块。Core和Beans模块是框架的基础部分,提供loC (转控制)和依赖注人特性。这里的基础概念是BeanFactory,它提供对Factory 模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
Data Access/Integration
Data Access/Integration层包含有JDBC、ORM、OXM、JMS和Transaction模块
Web
Web_上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。所以,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。Web层包含了Web、Web-Servlet、 Web Struts和Web-Porlet模块。
AOP
AOP模块提供了-一个符合AOP联盟标准的面向切面编程的实现,它让你可以定义例如方法拦截器和切点,从而将逻辑代码分开,降低它们之间的耦合性。利用source-level 的元数据功能,还可以将各种行为信息合并到你的代码中,这有点像.Net技术中的atribute概念。通过配置管理特性,Spring AOP模块直接将面向切面的编程功能集成到了Spring框架中,所以可以很容易地使Spring框架管理的任何对象支持AOP。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖EJB组件,就可以将声明性事务管理集成到应用程序中。
Test
Test模块支持使用JUnit和TestNG对Spring 组件进行测试
bean是Spring中最核心的东西,因为Spring就像是个大水桶,而bean就像是容器中的水,水桶脱离了水便也没什么用处了,那么我们先看看bean的定义。
public class MyTestBean {
private String testStr = "teststr";
public String getTestStr() {
return teststr;
public void setTestStr (String teststr) {
this.testStr = testStr;
很普通,bean没有任何特别之处,的确,Spring 的目的就是让我们的bean能成为- - 个纯
粹的POJO,这也是Spring所追求的。接下来看看配置文件:
在上面的配置中我们看到了bean 的声明方式,尽管Spring中bean的元素定义着N种属性来支撑我们业务的各种应用,但是我们只要声明成这样,基本上就已经可以满足我们的大多数应用了。好了,你可能觉得还有什么,但是真没了,Spring 的示例到这里已经结束,我们可以写测试代码测试了。
@SuppressWarnings ("deprecation")
public class BeanFactoryTest {
@Test
public void testSimpleLoad() {
BeanFactorybf = new XmlBeanFactory (new ClassPathResource ( "beanFactoryTest . xm1"));
MyTestBean bean= (NyTestBean) bf . getBean ("myTestBean");
assertEquals ("teststr" , bean. getTestStr());
}
相信聪明的读者会很快看到我们期望的结果:在Eclipse中显示了Green Baro直接使用BeanFactory作为容器对于Spring 的使用来说并不多见,甚至是甚少使用,因为在企业级的应用中大多数都会使用的是ApplicationContext(后续文章我们会介绍它们之间的区别),这里只是用于测试,让朋友们更快更好地分析Spring的内部原理
在4种标签的解析中,对bean标签的解析最为复杂也最为重要,所以我们从此标签开始深入分析,如果能理解此标签的解析过程,其他标签的解析自然会迎刃而解。
首先我们进入函数processBeanDefinition(ele, delegate)。
protected void processBeanDefinition (Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionlolder bdHolder - delegate .parseBeanDefinitionElement (ele) ;
if (bdHolder != null) {
bdHolder = de legate . decora teBeanDefini tionIfRequired (ele, bdHolder) ;
try {
BeanDefinitionReaderUtils .registerBeanDefinition (bdHolder, getReaderContext () .
getRegistry()) ;
catch
(BeanDefinitionStoreException ex) {
getReaderContext () .error ("Failed to register bean definition with name '" +
bdHolder . getBeanName() +"'", ele, ex);
}
getReaderContext () .fireComponentRegistered (new BeanCorponentDefinition (bdHolder));
}
}
乍一看,似乎一头雾水,没有以前的函数那样清晰的逻辑。大致的逻辑总结如下:
(1)首先委托BeanDefinitionDelegate类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder 类型的实例bdHolder,经过这个方法后,bdHolder 实例已经包含我们配置文件中配置的各种属性了,例如class、name、id、alias 之类的属性。
(2)当返回的bdHolder不为空的情况下若存在默认标签的子节点下再有自定义属性,还需要再次对自定义标签进行解析。
(3)解析完成后,需要对解析后的bdHolder 进行注册,同样,注册操作委托给了BeanDefinitionReaderUtils的registerBeanDefinition 方法。
(4)最后发出响应事件,通知相关的监听器,这个bean已经加载完成了。
在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直接基于Spring的标准bean来配置,当配置较为复杂或者需要更多丰富控制的时候,会显得非常笨拙。一般的做法会用原生态的方式去解析定义好的XML文件,然后转化为配置对象。这种方式当然可以解决所有问题,但实现起来比较繁琐,特别是在配置非常复杂的时候,解析工作是一一个不得不考虑的负担。
Spring 提供了可扩展Schema的支持,这是-一个不错的折中方案,扩展Spring自定义标签配置大致需要以下几个步骤:(前提是要把Spring的Core包加入项目中)
Bean加载过程中的步骤分为以下9步:
(1 )转换对应beanName
或许很多人不理解转换对应beanName是什么意思,传人的参数name不就是beanName吗?其实不是,这里传人的参数可能是别名,也可能是FactoryBean,所以需要进行一系列的解析,这些解析内容包括如下内容。去除 FactoryBean的修饰符,也就是如果name ="&aa", 那么会首先去除&而使name= "a".取指定 alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B;若别名A指向别名B,别名B又指向名称为C的bean则返回C。
(2)尝试从缓存中加载单例
单例在Spring的同一个容器内只会被创建-一次,后续再获取bean,就直接从单例缓存中获取了。当然这里也只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory 。
(3) bean的实例化
如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里有必要强调-下,缓存中记录的只是最原始的bean状态,并不- - 定是我们最终想要的bean。举个例子,假如我们需要对工厂bean 进行处理,那么这里得到的其实是工厂bean 的初始状态,但是我们真正需要的是厂bean 中定义的factory-method方法中返回的bean,而getObjectForBeanInstance就是完成这个工作的。
内容过多,后面几个小节点,小编我用图片代替:
设置了路径之后,便可以根据路径做配置文件的解析以及各种功能的实现了。可以说.refresh函数中包含了几乎ApplicationContext 中提供的全部功能,而且此函数中逻辑非常清晰明了,使我们很容易分析对应的层次及逻辑。内容过多,小编图片展示。
(1)创建用于拦截的bean
在实际工作中,此bean可能是满足业务需要的核心逻辑,例如test方法中可能会封装着某个核心业务,但是,如果我们想在test前后加入日志来跟踪调试,如果直接修改源码并不符合面向对象的设计方法,而且随意改动原有代码也会造成一定的风险,还好接下来的Spring 帮我们做到了这一点。
(2)创建Advisor
Spring中摒弃了最原始的繁杂配置方式而采用@AspectJ 注解对POJO进行标注,使AOP的工作大大简化,例如,在AspectTest类中,我们要做的就是在所有类的test 方法执行前在控制台中打印beforeTest,而在所有类的test方法执行后打印afterTest,同时又使用环绕的方式在所有类的方法执行前后再次分别打印beforel和after1。
(3)创建配置文件
XML是Spring的基础。尽管Spring 一再简化配置,并且大有使用注解取代XML配置之势,但是无论如何,至少现在XML还是Spring 的基础。要在Spring 中开启AOP功能,还需要在配置文件中作声明
(4)测试
经过以上步骤后,便可以验证Spring的AOP为我们提供的神奇效果了
尽管我们接触更多的是MyBatis与Spring的整合使用,但是MyBatis有它自己的独立使用方法,了解其独立使用的方法套路对分析Spring整合MyBatis非常有帮助,因为Spring无非就是将这些功能进行封装以简化我们的开发流程。
MyBatis 独立使用包括以下几步:
(1)建立PO
用于对数据库中数据的映射,使程序员更关注于对Java类的使用而不是数据库的操作
(2)建立Mapper
数据库操作的映射文件,也就是我们常常说的DAO,用于映射数据库的操作,可以通过配置文件指定方法对应的SQL语句或者直接使用Java提供的注解方式进行SQL指定。
(3)建立配置文件
配置文件主要用于配置程序中可变性高的设置,一个偏大的程序一定会存在一 些经常 会变化的变量,如果每次变化都需要改变源码那会是非常糟糕的设计,所以,我们看到各种各样的框架或者应用的时候都免不了要配置配置文件,MyBatis 中的配置文件主要封装在configuration中,配置文件的基本结构如图所示。
(4)建立映射文件
对应于MyBaits 全局配置中的mappers 配置属性,主要用于建立对应数据库操作接口的SQL映射。MyBatis会将这里设定的SQL与对应的Java接口相关联,以保证在MyBatis中调用接口的时候会到数据库中执行相应的SQL来简化开发。
Spring事务使用分为以下7步:
(1)创建数据表结构
(2)创建对应数据表的PO
(3)创建表与实体间的映射
(4)创建数据操作接口
(5)创建数据操作接口实现类
(6)创建Spring配置文件
(7)测试
Spring的快速体验有以下6步:
(1)配置web.xml
(2)创建Spring配置文件applicationContext.xml。
(3)创建model
(4)创建cololer
(5)创建视图文件usreistispo
(6)创建Servlet配置文件Spring- servlet.xml
希望转发点赞关注的朋友看完资料能破百度、战阿里、拼腾讯,拿到属于自己心中想要的offer。