***以下内容是假设你已经了解了springIOC***
传统的三层模式中,各层间需要互相调用,比如Service层需要调用Dao层的方法
既然需要调用方法,就需要先创建Dao层对应类的实例
单就在Service层创建Dao层类实例这块就产生了程序的耦合.
怎么才能解耦呢?
之前的学习过程中,通过将接口与其对应的实现类配置在了bean.properties中,再通过BeanFactory进行分析再创建实例对象
SpringIOC怎么知道去创建哪些对象到容器内呢?
需要我们人为的去指定要生产的内容,需要通过配置文件来配置.
SpringIOC采用什么配置文件来配置接口及其实现类之间的关系呢?
Answer:采用的文件格式是XML
SpringIOC为什么选择XML呢?
properties:复杂度不够,不支持中文,其主要用途是对数据库的配置
json:结构太轻且不够严谨,没有约束,其主要用于前后端数据的交互(不在乎格式,只在乎内容是什么)
XML:结构严谨,可以被约束(缺点是文件太大)
今天的引导学习会将思想逐渐的向SpringIOC上靠拢!
下面假设不知道SpringIOC技术的基础上,我们通过BeanFactory来实现程序解耦
- 需要创建哪些对象我们也通过文件来配置
- 配置文件的格式也选择XML
- 加载配置文件获取有效信息通过技术:dom4j+xpath
- 在BeanFactory的静态代码块中完成配置的加载
- 配置文件的结构:↓↓↓
- 键:id-->接口类文件名,开头字母小写
- 值:class-->对应的实现类全限定路径
一.案例展示
1.测试准备
项目工程:
2.代码展示
***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.howie</groupId>
<artifactId>springIOC_lazyload</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--dom4j-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!--xpath-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
</dependencies>
</project>
***ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="accountDao" class="com.howie.dao.impl.AccountDaoImpl"></bean>
<bean id="accountService" class="com.howie.service.impl.AccountServiceImpl"></bean>
</beans>
***BeanFactory.java
package com.howie.factory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author weihuanwen
* @Date 2019/8/13 21:55
* @Version 1.0
*/
public class BeanFactory {
//定义存储产生的对象的容器
private static Map<String,Object> objMap = new HashMap<>();
//用于生产对象的静态代码块
static {
SAXReader saxReader = new SAXReader();
InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("ApplicationContext.xml");
try {
//获取xml文件操作对象
Document document = saxReader.read(is);
//获取xaml文件根节点
Element rootElement = document.getRootElement();
//获取所有的bean页签
List<Element> beanList = rootElement.selectNodes("//bean");
if (beanList!=null && beanList.size()>0){
for (Element beanEle : beanList) {
//获取id
String id = beanEle.attributeValue("id");
//获取实现类的全限定类名
String classPath = beanEle.attributeValue("class");
Class clazz = Class.forName(classPath);
//实例化
Object obj = clazz.newInstance();
//将对象存储于map容器内
objMap.put(id,obj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 提供获取对象的方法
* @param key
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String key,Class<T> clazz){
return (T)objMap.get(key);
}
}
***Account.java
package com.howie.pojo;
/**
* @Author weihuanwen
* @Date 2019/8/13 21:53
* @Version 1.0
*/
public class Account {
private String id;
private String accountName;
private double money;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id='" + id + '\'' +
", accountName='" + accountName + '\'' +
", money=" + money +
'}';
}
}
***AccountDao.java
package com.howie.dao;
import com.howie.pojo.Account;
/**
* @Author weihuanwen
* @Date 2019/8/13 22:09
* @Version 1.0
*/
public interface AccountDao {
/**
* 保存账户信息
* @param account
*/
void saveAccount(Account account);
}
***AccountDaoImpl.java
package com.howie.dao.impl;
import com.howie.dao.AccountDao;
import com.howie.pojo.Account;
/**
* @Author weihuanwen
* @Date 2019/8/13 22:09
* @Version 1.0
*/
public class AccountDaoImpl implements AccountDao {
/**
* 保存账户信息,模拟存入数据的操作
* @param account account 账户对象
*/
@Override
public void saveAccount(Account account) {
System.out.println(account);
System.out.println("账户信息保存成功!");
}
}
***AccountService.java
package com.howie.service;
import com.howie.pojo.Account;
/**
* @Author weihuanwen
* @Date 2019/8/13 21:54
* @Version 1.0
*/
public interface AccountService {
/**
* 保存账户信息
* @param account
*/
void saveAccount(Account account);
}
***AccountServiceImpl.java
package com.howie.service.impl;
import com.howie.dao.AccountDao;
import com.howie.factory.BeanFactory;
import com.howie.pojo.Account;
import com.howie.service.AccountService;
/**
* @Author weihuanwen
* @Date 2019/8/13 21:54
* @Version 1.0
*/
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao = BeanFactory.getBean("accountDao",AccountDao.class);
/**
* 保存用户信息
* @param account
*/
@Override
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
}
***AccountTest.java
package com.howie.controller;
import com.howie.factory.BeanFactory;
import com.howie.pojo.Account;
import com.howie.service.AccountService;
import org.junit.Test;
/**
* @Author weihuanwen
* @Date 2019/8/13 22:21
* @Version 1.0
*/
public class AccountTest {
private AccountService accountService = BeanFactory.getBean("accountService",AccountService.class);
@Test
public void saveAccount(){
Account account = new Account();
account.setId("1");
account.setAccountName("Jhon");
account.setMoney(1000);
accountService.saveAccount(account);
}
}
3.测试
执行saveAccount()控制台输出
Account{id='1', accountName='Jhon', money=1000.0}
账户信息保存成功!
二.总结
1.BeanFactory的延迟加载怎么解释?
当调用getBean()方法的时候,BeanFactory会加载配置信息,并将所有对象全部创建出来
这种当需要时再去创建对象的形式就是延迟加载
2.什么时候需要延迟加载呢?
当为了追求传输效率就会需要什么就再去创建什么时,就会体现出延迟加载的好处