一、概述
1、spring的概述
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架(来自百度百科)。
2、控制反转(Inversion of Control,缩写为IoC)是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。(来自百度百科)
3、AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。(来自百度百科)
综上所述,很容易得出一个结论,spring框架的出现主要目的是为了降低项目中的耦合度,一种是代码之间的耦合度,一种是业务逻辑之间的耦合度。
二、程序的耦合和解耦
耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。
在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。
三、spring中基于XML的IOC配置
1、环境搭建
创建一个maven项目,模拟dao和service的环境,新建目录和对应的类,如下
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stevensam</groupId>
<artifactId>SpringTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
IStudentDao接口:
public interface IStudentDao {
void saveStudent();
}
StudentDao实现类:
public class StudentDao implements IStudentDao {
public StudentDao() {
System.out.println("对象创建了");
}
public void saveStudent() {
System.out.println("增加学生dao实现类执行了");
}
}
IStudentService接口:
public interface IStudentService {
void saveStudent();
}
StudentService实现类:
public class StudentService implements IStudentService{
private String name;
private Integer age;
private Date birthday;
private String[] myStrs;
private Set<String> mySet;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public StudentService(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
protected void finalize() throws Throwable {
System.out.println("对象销毁了");
}
public StudentService() {
System.out.println("对象创建了!");
}
public void saveStudent() {
System.out.println(name+","+age+","+birthday);
}
}
2、基本配置IOC步骤
(1)在test目录中新建beanTest测试类,创建spring框架容器ApplicationContext,用于从容器中获取对象:
public class beanTest {
@Test
public void test1(){
//运用ApplicationContext创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IStudentDao studentDao = (StudentDao)ac.getBean("studentDao");
System.out.println(studentDao);
}
}
(2)在resources目录下新建一个bean.xml,添加上约束头以及一行bean标签,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="studentDao" class="com.stevensam.dao.impl.StudentDao" scope="prototype"></bean>
<!--第一种创建方式,用的是默认构造方法创建对象-->
<bean id="studentDao" class="com.stevensam.dao.impl.StudentDao" scope="prototype"></bean>
</beans>
(3)测试结果如下图所示:
(4)BeanFactory
这里当然还可以用spring中的BeanFactory 来创建对象。BeanFactory是spring框架的心脏,是容器的顶层接口。
@Test
public void testBeanFactory(){
//运用BeanFactory创建对象
Resource resource = new ClassPathResource("bean.xml");
BeanFactory ac = new XmlBeanFactory(resource);
IStudentDao studentDao = (StudentDao)ac.getBean("studentDao");
System.out.println(studentDao);
}
(5)ApplicationContext
ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。它有三个常用实现类
ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用)
FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)
AnnotationConfigApplicationContext:它是用于读取注解创建容器的,会在下一篇博文中写到。
(6)bean标签的三种创建方式
第一种就是最先演示的方式。结果看上文
<!--第一种创建方式,用的是默认构造方法创建对象-->
<bean id="studentDao" class="com.stevensam.dao.impl.StudentDao" scope="prototype"></bean>
<bean id="studentService" class="com.stevensam.service.impl.StudentService"
init-method="saveStudent" destroy-method="finalize" scope="singleton"></bean>
第二种方式创建对象,用的是工厂类中的静态方法
<!--第二种方式创建对象,用的是工厂类中的静态方法-->
<bean id="studentService" class="com.stevensam.factory.StaticFactory" factory-method="getStudentService" scope="singleton" destroy-method="finalize"></bean>
StaticFactory类是非常简单的,代码如下:
public class StaticFactory {
//创建一个service实现类
public static StudentService getStudentService(){
return new StudentService();
}
}
第三种方式创建对象,用的是工厂类中的普通方法
<!--第三种方式创建对象,用的是工厂类中的普通方法-->
<bean id="factory" class="com.stevensam.factory.InstanceFactory"></bean>
<bean id="studentService" factory-bean="factory" factory-method="getStudentService" destroy-method="finalize" scope="singleton"></bean>
InstanceFactory类也是很简单,也是创建一个实现类返回:
public class InstanceFactory {
//普通方法创建service对象
public StudentService getStudentService(){
return new StudentService();
}
}
各自的结果,这里不提供了,读者可以直接粘贴代码运行,结果和上文的结果几乎一致。
(7)bean标签作用范围和生命周期
单例对象:scope=”singleton”一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销
多例对象:scope=”prototype”每次访问对象时,都会重新创建对象实例。
生命周期:对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被 java的垃圾回收器回
3、依赖注入(Dependency Injection)
它是 spring 框架核心 ioc 的具体实现。下面介绍几种方式的注入:
(1)构造函数注入
bean.xml可以再加上一下代码:
<!--依赖注入-->
<!--构造方法传参数,如果类中有无参构造,就不用传值,用上面演示的第一种方式创建即可-->
<bean id="studentService" destroy-method="finalize" class="com.stevensam.service.impl.StudentService" scope="singleton">
<constructor-arg name="name" value="test"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="date"></constructor-arg>
</bean>
<bean id="date" class="java.util.Date"></bean>
(2)set方法注入
<!--如果该类中有set方法,那么可以用下面的方式创建-->
<bean id="studentService" destroy-method="finalize" class="com.stevensam.service.impl.StudentService">
<property name="age" value="17"></property>
<property name="birthday" ref="date"></property>
<property name="name" value="张学友"></property>
</bean>
<bean id="date" class="java.util.Date"></bean>
(3)p文件注入
<!--需要在约束头里面加上xmlns:p="http://www.springframework.org/schema/p" 这句代码-->
<!--用p文件传值-->
<bean id="studentService" destroy-method="finalize"
class="com.stevensam.service.impl.StudentService"
p:age="20" p:birthday-ref="date" p:name="渣渣辉">
</bean>
<bean id="date" class="java.util.Date"></bean>
结果如下: