什么是Spring?
spring是分层的avaSE以及javaEE应用于全栈的轻量级开源框架,以IOC(Inverse Of Control)控制反转,AOP(Aspect Oriented Programing)面向切面编程为核心,提供表现层SpringMVC以及持久层Spring,并且可整合多种其他开源框架。
spring的本质是管理对象,包括创建对象及维护对象之间的关系。
spring的优点
1)方便解耦,简化开发
通过spring的IOC可将对象的创建,以及对象之间的依赖都交由spring容器来进行管理,这样可以降低程序之间的耦合。并且开发时也只需关注上层的应用,不用再多关注底层的应用。
2)AOP编程的支持
spring支持AOP面向切面编程,许多OOP面向对象编程不能或很难实现的功能,都可通过AOP轻松实现。
3)声明式事务的支持
可以将我们从单调烦闷的事务管理中解放出来,通过声明式事务的方式,可以灵活的进行事务管理,进而提高开发的质量和效率。
4)方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
5)方便集成各种优秀的框架
Spring可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持。
6)降低javaEE的API的使用难度
Spring对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些API 的使用难度大为降低。
7)spring框架的源码是经典学习的案例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对 Java技术的高深造诣。它的源代码无疑是Java技术的最佳实践的范例。
通过Spring进行解耦
什么叫程序的耦合?
在程序中,对象之间相互依赖,相互传递数据,这种相互关联的程度越高,程序的耦合度就越高。程序的耦合度越高,维护的成本就越高。
工厂模式解耦介绍
在实际开发中可以将分层的对象都配置到配置文件中,当需要这些对象时可以通过工厂加载配置文件创建出这些对象,在接下来需要使用的时候,直接拿过来使用就可以了。
可以通过 工厂+接口+配置文件的方式来解除程序间的耦合
Spring IOC控制反转
IOC(Inverse Of Control),将创建对象的权力交给Spring框架,即将对象的创建,存储,管理都交给spring容器进行管理。
spring容器是spring的一个核心模块,用来管理对象,底层可理解为一个map
Bean对象的单例(Singleton)和多例(prototype)
在Spring容器中管理Bean对象的作用域,可通过bean对象的scope属性来进行配置,通常用的是singleton和prototype两种。
1)singleton,单实例,是默认值,这个作用域标识的对象具有全局唯一性。
当一个bean的作用域被设置为singleton时,spring容器在全局只会为该bean创建一个实例,
这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的请求都会返回唯一的这一个实例。
singleton负责实例的创建,初始化,销毁
2)prototype,多实例,这个作用域标识的对象,每次获取时都会创建一个新的对象
当一个bean的作用域被标识为prototype时,每次请求,spring容器都会为该bean创建一个新的实例。
prototype负责实例的创建,初始化,不负责销毁
Spring DI依赖注入
DI(dependency injection),依赖注入,通常有两种不同的方式set方式注入和构造方式注入
依赖注入,即组件之间的依赖关系由容器在应用运行期间决定,即由容器在应用运行期间动态的将实例对象注入到所需依赖的组件中。
简而言之,依赖注入就是在创建对象同创建对象之后,动态的为对象属性赋值。
set方式注入
1)普通属性注入
示例:
创建需要赋值的对象
package com.tedu.spring;
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
<!-- 声明User类的bean实例 -->
<bean id="user" class="com.tedu.spring.User">
<!-- 通过set方式为普通属性赋值 -->
<property name="name" value="韩少云"></property>
<property name="age" value="20"></property>
</bean>
通过上述的方式就可以为对象的普通属性赋值。
注意:property标签中的name属性值,必须为对象中set方法名字,去掉set后第一个字母小写的名字。
例如:setUser()方法,它的name就应该为user
普通属性就可以通过value直接赋值
2)对象属性注入
代码示例:
public class User {
...
private UserInfo userInfo;
public UserInfo getUserInfo() {
return userInfo;
}
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
...
public String toString() {
return "User [name=" + name + ", age=" + age + ", userInfo=" + userInfo + "]";
}
}
在applicationContext.xml中
<!-- 声明User类的bean实例 -->
<bean id="user" class="com.tedu.spring.User">
<!-- 通过set方式为普通属性赋值 -->
<property name="name" value="韩少云"></property>
<property name="age" value="20"></property>
<!-- 通过set方式为对象属性赋值 -->
<property name="userInfo" ref="userInfo"></property>
</bean>
由于此处是将userInfo对象注入,所以ref的值为userInfo对象对应的bean的id,name与上述规则一致
对象通过ref注入
构造方法注入
代码示例:
//声明无参构造函数
public User() {
}
//声明有参构造函数
public User(String name, Integer age, UserInfo userInfo) {
super();
this.name = name;
this.age = age;
this.userInfo = userInfo;
}
applicationContext.xml文件
<bean id="user" class="com.tedu.spring.User">
<!-- 通过set方式为普通属性赋值
<property name="name" value="韩少云"></property>
<property name="age" value="20"></property>
<property name="userInfo" ref="userInfo"></property>
-->
<!-- 通过构造器中参数为属性赋值 -->
<constructor-arg name="name" value="马云"></constructor-arg>
<constructor-arg name="age" value="35"></constructor-arg>
<constructor-arg name="userInfo" ref="userInfo"></constructor-arg>
</bean>
<!-- 声明UserInfo类的bean实例 -->
<bean id="userInfo" class="com.tedu.spring.UserInfo"></bean>
其中constructor-arg的name值与构造方法中的入参保持一致
普通属性通过value赋值
对象属性通过ref赋值