Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
- 目的:解决企业应用开发的复杂性
- 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
- 范围:任何Java应用Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
程序的耦合
在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计 应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。
例如,Service层通过DAO层来new一个对象,那么DAO和Service就紧耦合了,但是DAO层和Service层可以通过DaoFactory来实现松耦合。
工厂模式解耦
accountService=cn.junko.service.impl.AccountServiceImpl
accountDao=cn.junko.dao.impl.AccountDaoImpl
package cn.junko.factory;
public class BeanFactory {
private static Properties props;
//定义一个Map,用于存放我们要创建的对象,称之为容器
private static Map<String,Object> beans;
static {
try {
props=new Properties();
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
props.load(in);
beans = new HashMap<String, Object>();
//取出配置文件的所有Key
Enumeration<Object> keys = props.keys();
//遍历枚举
while (keys.hasMoreElements()){
String key = keys.nextElement().toString();
String beanPath = props.getProperty(key);
Object value = Class.forName(beanPath).newInstance();
beans.put(key,value);
}
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化失败");
}
}
//多例
/* public static Object getBean(String beanName){
Object bean=null;
try {
String beanPath=props.getProperty(beanName);
bean=Class.forName(beanPath).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}*/
//单例
public static Object getBean(String beanName){
Object o = beans.get(beanName);
return o;
}
}
AccountService as=(AccountService)BeanFactory.getBean("accountDao");
System.out.println(as);
as.saveAccount();
IOC 控制反转
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
IOC环境搭建,需要导相应的jar包,或者添加坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
编写配置文件,这里命名是bean.xml,适用于默认构造函数注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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
">
<!--把对象的创建交给spring来管理-->
<bean id="aaccountService" class="cn.junko.service.impl.AccountServiceImpl"></bean>
<bean id="accountDao" class="cn.junko.dao.impl.AccountDaoImpl"></bean>
</beans>
通过bean获取对象的方法
public class Client {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
//根据id获取Bean对象
IAccountService as = (IAccountService) ac.getBean("accountService");
IAccountDao ad = ac.getBean("accountDao", IAccountDao.class);
}
}
ApplicationContext 接口的实现类
ClassPathXmlApplicationContext
:它是从类的根路径下加载配置文件 推荐使用这种
FileSystemXmlApplicationContext
:它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
AnnotationConfigApplicationContext
:当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
Spring的依赖注入
依赖注入是 spring 框架核心 ioc 的具体实现,在编写时,通过控制反转,把对象的创建交给了spring,但是代码中不可能出现没有依赖的情况。ioc解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取,有三种方法
- 构造函数注入
需要构造函数
使用构造函数的方式,给 service 中的属性传值
要求:类中需要提供一个对应参数列表的构造函数。
涉及的标签:constructor-arg
属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称 用这个找给谁赋值
上面三个都是找给谁赋值,下面两个指的是赋什么值的
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="pokey"></constructor-arg>
<constructor-arg name="age" value="23"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
- set方法注入
需要set方法
通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:property
属性:
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="name" value="junko"></property>
<property name="age" value="24"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
- 使用 p 名称空间注入数据(本质与set类似)