Create Spring

This commit is contained in:
Snakper 2020-04-21 16:06:41 +08:00 committed by GitHub
parent efeb9b3762
commit 27d841d553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

213
notes/Spring Normal file
View File

@ -0,0 +1,213 @@
1、 简述Spring框架
概念
Spring致力于Java EE应用的各种解决方案是一款轻量级框架大大简化了Java企业级开发提供了强大、稳定的功能。
Spring主要有两个目标一是让先有技术更易于使用二是促进良好的编程习惯(或者称为最佳实践)
优点
轻量级。 Spring在大小和透明性方面绝对属于轻量级的基础版本的Spring框架大约只有2MB
控制反转(IOC)。 Spring使用控制反转技术实现了松耦合。依赖被注入到对象而不是创建或寻找依赖对象。
方便解耦,简化开发
Spring就是一个大工厂可以将所有对象创建和依赖关系维护交给Spring管理
AOP编程的支持
Spring提供面向切面编程可以方便的实现对程序进行权限拦截、运行监控等功能
声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架其内部提供了对各种优秀框架Struts2、Hibernate、MyBatis、Quartz等的直接支持
降低JavaEE API的使用难度
Spring 对JavaEE开发中非常难用的一些APIJDBC、JavaMail、远程调用等都提供了封装使这些API应用难度大大降低
2、 Spring七大模块
Spring Core
Core封装包是框架的最基础部分提供IOC和依赖注入特性。这里的基础概念是BeanFactory它提供对Factory模式的经典实现来消除对程序性单例模式的需要并真正地允许你从程序逻辑中分离出依赖关系和配置。
Spring Context
i. 构建于Core封装包基础上的 Context封装包提供了一种框架式的对象访问方法有些象JNDI注册器。Context封装包的特性得自于Beans封装包并添加了对国际化I18N的支持例如资源绑定事件传播资源装载的方式和Context的透明创建比如说通过Servlet容器。
Spring DAO
i. DAO (Data Access Object)提供了JDBC的抽象层它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且JDBC封装包还提供了一种比编程性更好的声明性事务管理方法不仅仅是实现了特定接口而且对所有的POJOsplain old Java objects都适用。
Spring ORM
ORM 封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。
Spring AOP
i. Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现让你可以定义例如方法拦截器method-interceptors和切点pointcuts从逻辑上讲从而减弱代码的功能耦合清晰的被分离开。而且利用source-level的元数据功能还可以将各种行为信息合并到你的代码中。
Spring Web
Spring中的 Web 包提供了基础的针对Web开发的集成特性例如多方文件上传利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时这个包使Spring可与其他框架结合。
Spring Web MVC
Spring中的MVC封装包提供了Web应用的Model-View-ControllerMVC实现。Spring的MVC框架并不是仅仅提供一种传统的实现它提供了一种清晰的分离模型在领域模型代码和Web Form之间。并且还可以借助Spring框架的其他特性。
3、 Spring中的设计模式
spring中常用的设计模式达到九种我们举例说明
第一种:简单工厂
又叫做静态工厂方法StaticFactory Method模式但不属于23种GOF设计模式之一。 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。 spring中的BeanFactory就是简单工厂模式的体现根据传入一个唯一的标识来获得bean对象但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
第二种工厂方法Factory Method
通常由应用程序直接使用new创建新的对象为了将对象的创建和使用相分离采用工厂模式,即应用程序将对象的创建及初始化职责交给工厂对象。一般情况下,应用程序有自己的工厂对象来创建bean.如果将应用程序自己的工厂对象交给Spring管理,那么Spring管理的就不是普通的bean,而是工厂Bean。
第三种单例模式Singleton
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
spring中的单例模式完成了后半句话即提供了全局的访问点BeanFactory。但没有从构造器级别去控制单例这是因为spring管理的是是任意的java对象。
第四种适配器Adapter
在Spring的Aop中使用的Advice通知来增强被代理类的功能。Spring实现这一AOP功能的原理就使用代理模式1、JDK动态代理。2、CGLib字节码生成技术代理。对类进行方法级别的切面增强生成被代理类的代理类 并在代理类的方法前,设置拦截器,通过执行拦截器重的内容增强了代理方法的功能,实现的面向切面编程。
第五种包装器Decorator
在我们的项目中遇到这样一个问题我们的项目需要连接多个数据库而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在spring和hibernate框架中总是配置一个数据源因而sessionFactory的dataSource属性总是指向这个数据源并且恒定不变所有DAO在使用sessionFactory的时候都是通过这个数据源访问数据库。但是现在由于项目的需要我们的DAO在访问sessionFactory的时候都不得不在多个数据源中不断切换问题就出现了如何让sessionFactory在执行数据持久化的时候根据客户的需求能够动态切换不同的数据源我们能不能在spring的框架下通过少量修改得到解决是否有什么设计模式可以利用呢 首先想到在spring的applicationContext中配置所有的dataSource。这些dataSource可能是各种不同类型的比如不同的数据库Oracle、SQL Server、MySQL等也可能是不同的数据源比如apache 提供的org.apache.commons.dbcp.BasicDataSource、spring提供的org.springframework.jndi.JndiObjectFactoryBean等。然后sessionFactory根据客户的每次请求将dataSource属性设置成不同的数据源以到达切换数据源的目的。
spring中用到的包装器模式在类名上有两种表现一种是类名中含有Wrapper另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。
第六种代理Proxy
为其他对象提供一种代理以控制对这个对象的访问。 从结构上来看和Decorator模式类似但Proxy是控制更像是一种对功能的限制而Decorator是增加职责。
spring的Proxy模式在aop中有体现比如JdkDynamicAopProxy和Cglib2AopProxy。
第七种观察者Observer
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
spring中Observer模式常用的地方是listener的实现。如ApplicationListener。
第八种策略Strategy
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
第九种模板方法Template Method
定义一个操作中的算法的骨架而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Template Method模式一般是需要继承的。这里想要探讨另一种对Template Method的理解。spring中的JdbcTemplate在用这个类时并不想去继承这个类因为这个类的方法太多但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接那么我们怎么办呢我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码而且这段代码会用到JdbcTemplate中的变量。怎么办那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法我们去实现这个方法就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate从而完成了调用。这可能是Template Method不需要继承的另一种实现方式吧。
4、 ApplicationContext与BeanFactory的区别
两者都是通过xml配置文件加载bean,ApplicationContext和BeanFacotry相比,提供了更多的扩展功能,但其主要区别在于后者是延迟加载,如果Bean的某一个属性没有注入BeanFacotry加载后直至第一次使用调用getBean方法才会抛出异常而ApplicationContext则在初始化自身是检验这样有利于检查所依赖属性是否注入所以通常情况下我们选择使用ApplicationContext。
BeanFactroy采用的是延迟加载形式来注入Bean的即只有在使用到某个Bean时(调用getBean())才对该Bean进行加载实例化这样我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反它是在容器启动时一次性创建了所有的Bean。这样在容器启动时我们就可以发现Spring中存在的配置错误。
BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用但两者之间的区别是BeanFactory需要手动注册而ApplicationContext则是自动注册
5、 如何理解IoC和DI
1、IOC IOC就是控制反转通俗的说就是我们不用自己创建实例对象这些都交给Spring的bean工厂帮我们创建管理。这也是Spring的核心思想通过面向接口编程的方式来是实现对业务组件的动态依赖。这就意味着IOC是Spring针对解决程序耦合而存在的。在实际应用中Spring通过配置文件xml或者properties指定需要实例化的java类类名的完整字符串包括这些java类的一组初始化值通过加载读取配置文件用Spring提供的方法getBean())就可以获取到我们想要的根据指定配置进行初始化的实例对象。
优点IOC或依赖注入减少了应用程序的代码量。它使得应用程序的测试很简单因为在单元测试中不再需要单例或JNDI查找机制。简单的实现以及较少的干扰机制使得松耦合得以实现。IOC容器支持勤性单例及延迟加载服务。
2、DIDI—Dependency Injection即“依赖注入”组件之间依赖关系由容器在运行期决定形象的说即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能而是为了提升组件重用的频率并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制我们只需要通过简单的配置而无需任何代码就可指定目标需要的资源完成自身的业务逻辑而不需要关心具体的资源来自何处由谁实现。
6、 AOP相关术语
切面Aspect一个模块化的横切逻辑(或称横切关注点),可能会横切多个对象。
连接点(Join Point)程序执行中的某个具体的执行点。入原对象的fun()方法就是一个连接点。
增强处理Advice切面在某个特定连接点上执行的代码逻辑。
切入点Ponitcut对连接点的特征进行描述可以使用正则表达式。增强处理和一个切入点
表达式相关联,并在与这个切入点匹配的某个连接点上运行。
目标对象Target object被一个或多个切面增强的对象。
AOP代理AOP proxy由AOP框架所创建的对象实现执行增强处理方法等功能。
织入Weaving将增强处理连接到应用程序中的类型或对象上的过程。
7、 如何理解Spring AOP
1、概念
面向切面编程。AOP是OOP的延续是软件开发中的一个热点也是Spring框架中的一个重要内容利用AOP可以对业务逻辑的各个部分进行隔离从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性同时提高了开发的效率。
2、 核心思想
可以在不修改源代码的前提下,对程序进行增强
3、实现原理
Spring框架的AOP技术底层也是采用的代理技术所谓的动态代理就是说 AOP 框架不会去修改字节码,而是在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法 。Spring AOP 中的动态代理主要有两种方式, JDK 动态代理和 CGLIB 动态代理 。
JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口 。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类 。
如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类 。CGLIB Code Generation Library ),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意, CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final ,那么它是无法使用 CGLIB 做动态代理的 。
8、 Spring中有哪些增强处理区别
前置增强org.springframework.aop.BeforeAdvice代表前置增强表示在目标方法整形前实施增强
后置增强org.springframework.aop.AfterReturningAdvice代表后置增强表示在目标方法执行后实施增强
环绕增强org.springframework.aop.MethodInterceptor代表环绕增强表示在目标方法执行前后实施增强
异常抛出增强 org.springframework.aop.ThrowsAdvice代表抛出异常增强表示在目标方法抛出异常后实施增强
引介增强org.springframework.aop.IntroductionInterceptor代表引介增强表示在目标类中添加一些新的方法和属性
9、 Spring多种方式注入值
依赖注入通常有如下两种:
i. 设值注入IoC容器使用属性的setter方法来注入被以依赖的实例
ii. 构造注入IoC容器使用构造器来注入被依赖的实例。
设值注入
i. 设值注入是指IoC容器使用属性的setter方法来注入被依赖的实例。
Bean与Bean之间的依赖关系有Spring管理Spring采用setter方法为目标Be阿玛尼注入所依赖的Bean这种方式被称之为设值注入。从上面的实例我们可以看出依赖注入以配置文件管理Bean实例之间的耦合让Bean实例之间的耦合从代码层次分离出来。
构造注入
构造注入就是利用构造器来设置依赖关系的方式。构造注入的配置文件需要做一些修改。为了使用构造注入,使用元素来指定构造器的参数。
两种注入方式的对比
i. Spring支持两种依赖注入方式这两种依赖注入方式并没有好坏之分只是适合的场景有所不同。
设值注入有如下优点:
与传统的JavaBean的写法更相似程序开发人员更加容易理解接受。通过setter方法设定依赖关系显得更加直观、自然。
对于复杂的依赖关系如果采用构造注入会导致构造器过于臃肿难以阅读。Spring在创建Bean实例时需要同时实例化其依赖的全部实例因此导致性能下降。而设值注入则可以避免这些问题。尤其是在某些属性可选的情况下多参数的构造器更加笨重。
但是构造器也有如下优势:
构造注入可以再构造器中决定依赖关系的注入顺序,优先依赖的优先注入。
对于依赖关系无须变化的Bean构造注入更有用处。因为没有setter方法所有的依赖关系全部在构造器中设定因此无须担心后续的代码对依赖关系产生破坏。
依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更加符合高内聚的原则。
通过上面的对比。所以建议用以设值注入为主,构造注入为辅的注入策略。对于依赖关系无须变化的注入,尽量采用构造注入;而其他的依赖关系,则考虑设值注入。
10、 Spring中支持的Bean作用域
支持如下五种不同的作用域
Singleton默认在Spring IOC容器中仅存在一个Bean实例Bean以单实例的方式存在。
Prototype一个bean可以定义多个实例
Request每次HTTP请求都会创建一个新的Bean。该作用域仅适用于WebApplicationContext环境。
Session一个HTTP Session定义一个Bean。该作用域仅适用于WebApplicationContext环境.
GolbalSession同一个全局HTTP Session定义一个Bean。该作用域同样仅适用于WebApplicationContext环境.
11、 如何定义bean的作用域
在Spring中创建一个bean的时候我们可以声明它的作用域。只需要在bean定义的时候通过scope属性定义即可。例如当Spring需要产生每次一个新的bean实例时应该声明bean的scope属性为prototype。如果每次你希望Spring返回一个实例应该声明bean的scope属性为singleton。
12、Spring框架中的bean的生命周期
Spring容器读取XML文件中bean的定义并实例化bean。
Spring根据bean的定义设置属性值。
如果该Bean实现了BeanNameAware接口Spring将bean的id传递给setBeanName()方法。
如果该Bean实现了BeanFactoryAware接口Spring将beanfactory传递给setBeanFactory()方法。
如果任何bean BeanPostProcessors 和该bean相关Spring调用postProcessBeforeInitialization()方法。
如果该Bean实现了InitializingBean接口调用Bean中的afterPropertiesSet方法。如果bean有初始化函数声明调用相应的初始化方法。
如果任何bean BeanPostProcessors 和该bean相关调用postProcessAfterInitialization()方法。
如果该bean实现了DisposableBean调用destroy()方法。
13、哪些是最重要的bean声明周期方法是否能重写它们
有两个重要的bean生命周期方法。第一个是setup方法该方法在容器加载bean的时候被调用。第二个是teardown方法该方法在bean从容器中移除的时候调用。
bean标签有两个重要的属性(init-method 和 destroy-method)你可以通过这两个属性定义自己的初始化方法和析构方法。Spring也有相应的注解@PostConstruct 和 @PreDestroy。
14、spring中自动装配的方式有哪些
No即不启用自动装配。
byName通过属性的名字的方式查找JavaBean依赖的对象并为其注入。比如说类Computer有个属性printer指定其autowire属性为byName后Spring IoC容器会在配置文件中查找id/name属性为printer的bean然后使用setter方法为其注入。
byType通过属性的类型查找JavaBean依赖的对象并为其注入。比如类Computer有个属性printer类型为Printer那么指定其autowire属性为byType后Spring IoC容器会查找Class属性为Printer的bean使用setter方法为其注入。
constructor通byType一样也是通过类型查找依赖对象。与byType的区别在于它不是使用setter方法注入而是使用构造子注入。
autodetect在byType和constructor之间自动的选择注入方式。
default由上级标签的default-autowire属性确定。
15、有几种不同类型的自动代理
BeanNameAutoProxyCreator
DefaultAdvisorAutoProxyCreator
Metadata autoproxying
16、什么是Spring的内部bean
当一个bean仅被用作另一个bean的属性时它能被声明为一个内部bean为了定义inner bean在Spring 的 基于XML的 配置元数据中,可以在 或 元素内使用 元素内部bean通常是匿名的它们的Scope一般是prototype。
17、自动装配有哪些局限性?
重写: 仍需用 和 配置来定义依赖,意味着总要重写自动装配。
基本数据类型不能自动装配简单的属性如基本数据类型String字符串和类。
模糊特性:
自动装配不如显式装配精确,如果有可能,建议使用显式装配。
18、Spring框架的事务管理有哪些优点
它为不同的事务API 如 JTA,JDBCHibernate,JPA 和JDO提供一个不变的编程模式。
它为编程式事务管理提供了一套简单的API而不是一些复杂的事务API如
它支持声明式事务管理。
它和Spring各种数据访问抽象层很好得集成。