耦合: 程序间(类、方法)的依赖关系
解耦:降低程序间的依赖关系,应该做到编译器不依赖,运行时才依赖。
解耦思路:使用反射来创建对象,避免使用new;通过读取配置文件来获取要创建对象的全限定类名。
分别创建:
持久层接口:
public interface AccountDao {
/**
* 模拟保存
*/
void saveAccount();
}
持久层实现类:
public interface AccountDao {
/**
* 模拟保存
*/
void saveAccount();
}
业务层接口:
public interface AccountService {
/**
* 模拟保存
*/
void saveAccount();
}
业务层实现类:
public class AccountServiceImpl implements AccountService {
AccountDao accountDao = new AccountDaoImpl();
public void saveAccount() {
accountDao.saveAccount();
}
}
模拟view层:
public class Client {
public static void main(String[] args) {
AccountService accountService = new AccountServiceImpl();
accountService.saveAccount();
}
}
这样使用会在视图层调用业务层;业务层调用持久层的方法。如果其中某个类出现缺失等问题,则会在程序编译时报错,耦合性太高了。所以下面使用工厂类来映射对象减少程序间的耦合行。
工厂类:
/** 创建Bean对象的工厂
* bean:在计算机英语中为可重用组件。
*
* JavaBean:用Java语言编写的可重用组件。
*
* 这个类用于创建Service和Dao对象
* 1. 需要一个配置文件来配置service和dao
* 配置内容:唯一表示=全限定类名(key=value)
* 可以是xml也可以是properties
* 2. 读取配置文件中的内容,反射创建对象
*/
public class BeanFactory {
// 定义一个Properties对象
private static Properties properties;
// 定义一个Map容器用于存放要创建的对象
private static Map<String ,Object> beans;
static {
try {
// 实例化对象
properties = new Properties();
// 获取配置对象流(使用类加载器获取)
InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
// 加载配置文件
properties.load(inputStream);
// 实例化容器
beans = new HashMap<String, Object>();
// 取出配置文件中所有的kay
Enumeration<Object> keys = properties.keys();
// 遍历枚举
while (keys.hasMoreElements()){
// 取出key
String key = keys.nextElement().toString();
// 根据key获取value
String beanPath = properties.getProperty(key);
// 创建反射对象
Object value = Class.forName(beanPath).newInstance();
beans.put(key,value);
}
} catch (IOException e) {
e.printStackTrace();
throw new ExceptionInInitializerError("初始化配置文件失败");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 根据bean名称获取对象
* @param beanName
* @return
*/
public static Object getBean(String beanName){
return beans.get(beanName);
}
}
bean.properties:
accountService=com.springDemo.service.Impl.AccountServiceImpl
accountDao=com.springDemo.dao.Impl.AccountDaoImpl
然后修改业务层实现类和模拟的试图层:
业务层实现类
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");
// AccountDao accountDao = new AccountDaoImpl();
public void saveAccount() {
accountDao.saveAccount();
}
}
模拟试图层:
public class Client {
public static void main(String[] args) {
AccountService accountService = (AccountService) BeanFactory.getBean("accountService");
// AccountService accountService = new AccountServiceImpl();
accountService.saveAccount();
}
}
以达到减少耦合的目的。
指app和资源之间没有必然的联系,使用工厂类去联系拥有独立的控制。把对象创建的权力交给框架。
用于削减耦合。
spring依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
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-3.2.xsd">
<!--把对象的创建交给spring来管理-->
<bean id="accountService" class="com.springDemo.service.Impl.AccountServiceImpl"></bean>
<bean id="accountDao" class="com.springDemo.dao.Impl.AccountDaoImpl"></bean>
</beans>
模拟试图:
public class Client {
public static void main(String[] args) {
// 获取springIoC核心容器并且获取id对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
// 根据id获取bean对象 下面两种方法都可以
AccountService accountService = (AccountService) applicationContext.getBean("accountService");
AccountService accountService1 = applicationContext.getBean("accountService",AccountService.class);
accountService.saveAccount();
}
}
ApplicationContext下的三个常用实现类:
ApplicationContext与BeanFactory:
Spring创建Bean的三种方式:
<bean id="accountService" class="com.springDemo.service.Impl.AccountServiceImpl"></bean>
<bean id="BeanFactory" class="com.springDemo.factory.BeanFactory"></bean>
<bean id="accountService" factory-bean="BeanFactory" factory-method="getAccountService"></bean>
方法:
public AccountService getAccountService(){
return new AccountServiceImpl();
}
<bean id="accountService" class="com.springDemo.factory.BeanFactory" factory-method="getStaticAccountService"></bean>
public static AccountService getStaticAccountService(){
return new AccountServiceImpl();
}
Bean的作用范围:
scope属性:
Bean对象的生命周期:
依赖关系的维护就称之为依赖注入。
经常改变的数据不使用注入。
<!--复杂类型的注入-->
<bean id="accountService" class="com.springDemo.service.Impl.AccountServiceImpl">
<!--注入数组-->
<property name="myStrs">
<array>
<value>AAA</value>
<value>AAA</value>
<value>AAA</value>
</array>
</property>
<!--注入list-->
<property name="myList">
<list>
<value>BBB</value>
<value>BBB</value>
<value>BBB</value>
</list>
</property>
<!--注入set-->
<property name="mySet">
<set>
<value>BBB</value>
<value>BBB</value>
<value>BBB</value>
</set>
</property>
<!--注入Map-->
<property name="myMap">
<map>
<entry key="testA" value="aaa"></entry>
<entry key="testB">
<value>BBB</value>
</entry>
<entry key="testA" value="aaa"></entry>
</map>
</property>
<!--注入Props-->
<property name="myProps">
<props>
<prop key="A">aa</prop>
<prop key="A">aa</prop>
<prop key="A">aa</prop>
</props>
</property>
</bean>
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name,Integer age,Date birthday){
this.name = name;
this.age = age;
this.birthday = birthday;
}
<bean id="accountService" class="com.springDemo.service.Impl.AccountServiceImpl">
<constructor-arg name="age" value="1"></constructor-arg>
<constructor-arg name="name" value="Tom"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
<!--set注入-->
<bean id="accountService" class="com.springDemo.service.Impl.AccountServiceImpl">
<property name="name" value="text"></property>
<property name="birthday" ref="now"></property>
<property name="age" value="1"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>