一.Spring简介
1.简介
Spring 是一个开源的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。2002 年,Rod Jahnson 首次推出了 Spring 框架雏形 interface21 框架。2004 年3月24日,Spring 框架以 interface21 框架为基础,经过重新设计,发布了 1.0正式版。
2.优点
1.方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
2.AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
3.声明事物的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
4.方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5.方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
6.降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
7.Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
3.Spring框架的作用
Spring是一个JavaEE一站式的开发框架。它提供的功能涵盖了JavaEE程序中的表示层,服务层,持久层功能组件。这意味着,使用了Spring框架,一个框架就可以满足整个JavaEE程序的开发。
但Spring框架,更加强调的是它的轻量级(模块的可插拔)!!也就是说,除了内核以外模块,如果你不想使用可以不用,它能够整合任何第三方的框架。所以,在现实开发中,Spring主要用于整合其他框架。
二.Spring框架中的模块
使用Spring框架之前,我们简单了解一下这个框架由哪些模块构成。Spring本身具有非常好的模块化架构,包含了20多个模块。这些模块划分为六大部分,可以单独使用,也可以组合使用。下面这张图是Spring官方文档给出的Spring概览图。
三.spring核心原理
1.IOC控制反转
概念:控制权由对象本身转向容器,由容器根据配置文件创建对象实例并实现各个对象的依赖关系。
核心:bean工厂
2.AOP面向切面编程
a.静态代理
根据每个具体类分别编写代理类
根据一个接口编写一个代理类
b.动态代理
针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类
四.Spring(DI)依赖注入
1.依赖简介
一个典型的企业应用程序不是由一个单一的对象组成(或Spring的说法中的bean)。即使是最简单的应用程序也只有几个对象一起工作来呈现最终用户看作是一个连贯的应用程序。如何从定义许多独立的bean定义到完全实现的应用程序,在这些应用程序中对象协作实现目标。有关spring的设计模式和应用详情可以参考我这篇文章《spring常用设计模式及应用》
2.依赖注入
依赖注入(DI)是一个过程,通过这个过程,对象可以通过构造函数参数,工厂方法的参数或者在构造或返回对象实例后设置的属性来定义它们的依赖关系从工厂方法。然后容器在创建bean时注入这些依赖关系。这个过程从根本上说是相反的,因此名为控制反转(IoC),它本身通过使用类的直接构造或服务定位符模式来控制它自己的依赖关系的实例化或位置。代码与DI原则相比更加清晰,当对象提供依赖时,解耦更为有效。该对象不查找它的依赖关系,不知道依赖关系的位置或类。因此,您的类变得更容易测试,特别是当依赖关系在接口或抽象基类上时,它们允许在单元测试中使用存根或模拟实现。DI存在两种主要的变体,基于构造函数的依赖注入和基于Setter的依赖注入。
3.基于构造函数的依赖注入
基于构造器的 DI通过容器调用具有多个参数的构造器来完成,每个参数表示一个依赖关系。调用static具有特定参数的工厂方法来构造这个bean几乎是等价的,而且这个讨论同样将参数作为构造函数和static工厂方法来处理。以下示例显示了只能通过构造函数注入进行依赖注入的类。请注意,这个类没有什么特别之处,它是一个POJO,它不依赖于容器特定的接口,基类或注释。
public class SimpleMovieLister {
private MovieFinder movieFinder;
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
(1).构造器参数匹配
构造函数参数解析匹配使用参数的类型进行。如果bean定义的构造函数参数中没有潜在的歧义,那么bean定义中定义构造函数参数的顺序就是在实例化bean时将这些参数提供给适当构造函数的顺序。
package x.y;public class Foo {
public Foo(Bar bar, Baz baz) {
// ...
}
}
没有潜在的歧义存在,假设Bar和Baz不是继承关系。因此,以下配置好,你不需要指定构造器参数指标明确在 索引,类型或类型。
<beans>
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
</bean>
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
</beans>
在前面的场景中,如果使用类型属性显式地指定构造函数参数的类型,容器可以使用与简单类型的类型匹配。
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
使用索引属性指定显式构造函数参数的指数。
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>同样也可以使用构造器参数名称匹配
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
(2).基于Setter方法
在调用无参数构造函数或无参数静态工厂方法实例化bean时,基于bean的调用Setter方法是通过bean调用Setter方法完成的。
public class SimpleMovieLister {private MovieFinder movieFinder;
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
Spring团队通常提倡构造函数注入,因为它使一个能够将应用程序组件作为不可变对象实现,并确保所需的依赖项不是null。此外,构造函数注入的组件总是返回到完全初始化状态的客户机(调用)代码中。作为一个方面说明,大量的构造函数的参数是一个糟糕的代码的气味,这意味着类可能有太多的责任和应该被更好的问题解决的适当分离。
Setter注入应该主要用于可选的依赖关系,这些依赖关系可以在类中分配合理的默认值。否则,非空检查必须在代码使用依赖项的任何地方执行。第=一个优势就是在于setter方法使该类的对象能够重新配置或重新注入。因此通过JMX MBean管理是setter注入一个引人注目的用例.
五.复杂类型注入的方法
1.list
注入普通类型或者字符串类型的时候如下:
<bean name="person" class="com.woder.spring.pojo.Person">
<property name="nameList">
<list>
<value>小红</value>
<value>小黄 </value>
<value>小兰 </value>
</list>
</property>
</bean>
当注入的数组类型的元素是对象的时候,需要用到ref bean:
<bean name="person" class="com.woder.spring.pojo.Person">
<property name="carList">
<list>
<ref bean="personCar1"/>
<ref bean="personCar2"/>
</list>
</property>
</bean>
2.set
<bean name="person" class="com.woder.spring.pojo.Person">
<property name="nameSet">
<set>
<value>小红</value>
<value>小黄 </value>
<value>小兰 </value>
</set>
</property>
</bean>
当Set的元素为对象的时候
<bean name="person" class="com.woder.spring.pojo.Person">
<property name="nameSet">
<set>
<ref bean="personCar1"/>
<ref bean="personCar2"/>
</set>
</property>
</bean>
3.map
<bean name="person" class="com.woder.spring.pojo.Person">
<property name="nameCarMap">
<map>
<!--普通的字符串-->
<entry key="小红" value="BMW" ></entry>
<!---注入的类型的对象的时候->
<entry key="小黄" value-ref="car" ></entry>
</map>
</property>
</bean>
4.propert
<bean name="person" class="com.woder.spring.pojo.Person">
<property name="properties">
<props>
<prop key="username" >root</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>