1.什么是Spring
Spring是一个轻量级的JavaEE解决方案,整合众多优秀的设计模式
- 轻量级
1.对于运行环境是没有额外要求的
开源 tomcat resion jetty
收费 weblogic websphere
2. 代码移植性高
不需要实现额外接口
- JavaEE的解决方案
- 整合设计模式
- 工厂
- 代理
- 模板
- 策略
2.设计模式
1.广义概念
面向对象设计中,解决特定问题的经典代码
2.狭义概念
GDF4人帮定义的23种设计模式:工厂、适配器、装饰器、门面、代理、模板......
2.1工厂设计模式
1.概念:通过工厂类创建对象
2.好处:解耦合
耦合:指的是代码间的强关联关系,一方的改变会影响另一方
问题:不利于代码维护
简单的理解为把接口的实现类,硬编码在程序中:
UserService userService = new UserServiceImpl();
2.2 如何理解耦合
下面通过一段代码帮助理解耦合:
1.创建持久层接口和实现类
package com.dao;
/** 模拟持久层操作 * */
public interface IAccountDao {
void saveAccount();
}
//---------------------------------
package com.dao.impl;
import com.dao.IAccountDao;
public class AccountDaoimpl implements IAccountDao {
public void saveAccount() {
System.out.println("保存了账户");
}
2.创建业务层接口和实现类
package com.service;
/** 模拟业务层接口 * */
public interface IAccountService {
//模拟保存
void saveAccount(); }
// -----------------------------------
package com.service.impl;
import com.dao.IAccountDao;
import com.dao.impl.AccountDaoimpl;
import com.service.IAccountService;
public class AccountServiceImpl implements IAccountService {
//业务层中获取持久层对象
private IAccountDao accountDao=new AccountDaoimpl();
public void saveAccount() { //业务层调用持久层dao接口
accountDao.saveAccount();
}
}
3.表现层调用
import com.service.IAccountService;
import com.service.impl.AccountServiceImpl;
/** 模拟表现层调用业务层 * */
public class Client {
public static void main(String[] args) {
//下面这句也有耦合,假如AccountServiceImpl改变功能成AccountServiceImplNew();
//则就要 IAccountService accountService = new AccountServiceImplNew();
IAccountService accountService = new AccountServiceImpl();
accountService.saveAccount();
}
}
这个时候运行时毫无疑问的,但是该项目之间类与类之间的依赖关系是非常紧密的,这就是我们需要进行解决的问题,类与类之间的依赖过高,耦合性太强。
(我们可以试想下,当把持久层的实现类给删掉的话,那么整个程序就会出现编译时期的错误,注意,这里是错误,而不仅仅是异常)
2.3工厂模式常见对象
public class BeanFactory {
//工厂方法只用于创建对象 是个工具类
public static UserService getUserService(){
//让耦合出现在了这里
return (UserService) new UserServiceImpl();
}
}
//====================
public class TestSpring {
@Test
public void test1(){
//原本耦合代码:
UserServiceImpl userService1 = new UserServiceImpl();
//通过工厂类获取对象 消除耦合
UserService userService =BeanFactory.getUserService();
//在这里已经没有耦合 因为接口UserService的实现类在这句代码中是没有任何体现的。
}
}
3.只使用反射可以消除耦合吗?
Class clazz = Class.forName("com.dy.basic.UserServiceImpl");
//(耦合字符串)在这句字符串中出现了耦合,因为如果UserServiceImpl要修改成UserServiceImplNew,又要改这句代码。
UserService userService = (UserService) clazz.newInstance();
return userService;
4.如何彻底消除(转移)耦合–(反射+配置文件)
#key-value形式
userService = com.dy.basic.UserServiceImpl
public class BeanFactory {
//Properties类型的集合
private static Properties env = new Properties();
static {
//第一步 获得IO输入流 getResourceAsStream()方法以InputStream对象的形式返回此类的指定资源。
InputStream inputStream = BeanFactory.class.getResourceAsStream("/dy.properties");
//第二步 在resources文件夹下 创建配置文件dy.properties 文件内容 封装 Properties集合中
//key = userService value = com.dy.basic.UserServiceImpl
//userService = com.dy.basic.UserServiceImpl
//这一步将文件当中的key作为了Properties集合中的key,文件中的value作为了Properties集合中的value;
env.load(inputStream);
inputStream.close();
}
//工厂方法只用于创建对象 工具类
public static UserService getUserService() {
//userService作为key传过来,取到值com.dy.basic.UserServiceImpl
Class clazz = Class.forName(env.getProperty("userService"));
UserService userService = (UserService) clazz.newInstance();
return userService;
}
}
/*
如果创建了新的实现类UserServiceImplNew,则只需要在配置文件中将
userService = com.dy.basic.UserServiceImpl改成
userService = com.dy.basic.UserServiceImplNew即可
*/
5.通用工厂的设计(简单工厂会存在代码冗余)
public static UserService getUserService() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
UserService userService = null;
//userService作为key传过来,取到值com.dy.basic.UserServiceImpl
Class clazz = Class.forName(env.getProperty("userService"));
//这个方法在上述的类BeanFactory 里 env是Properties集合的对象
userService = (UserService) clazz.newInstance();
return userService;
}
public static UserDao getUserDao() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
UserDao userDao = null;
Class clazz = Class.forName(env.getProperty("userDao"));
userDao = (UserDao) clazz.newInstance();
return userDao;
如上述代码所示,每次创建一个对象都需要创建一个方法,方法中有冗余代码(重复的代码多),不一样的代码就是env.getProperty("userDao")这一句。如何消除冗余代码呢?
一般方法的结构:修饰符+返回值+方法名+参数(可有可无)+异常(可有可无)
通过观察上述工厂的方法写出通用方法:
public static Object getBean(String key){
Object ret = null;
try{//上述代码是直接抛出的异常,这里我们用try catch
Class clazz = Class.forName(env.getProperty(key));
ret = clazz.newInstance();
}catch(Exception e){
e.printStackTrace();
}
return ret;
}
//通用代码写完后,将冗余代码注释掉,此时需要修改实现类UserServiceImpl和测试类的代码:
private UserDao userDao;
{
try {
//因为getBean()返回的是Object,实际我们需要的是UserDao,所以得强制类型转换
userDao = (UserDao) BeanFactory.getBean("userDao");
//修改之前是 userDao = (UserDao) BeanFactory.getUserDao();
} catch (Exception e) {
e.printStackTrace();
}
通用工厂的使用方式
1.定义类型(类)
2.通过配置文件的配置告知工厂 key = value
3.通过工厂获得类的对象
Object ret = BeanFactory.getBean("key")
-------------------------------------------------
Spring本质:工厂 ApplicationContext( applicationContext.xml)
本系列文章从Spring5原理开始深入浅出,从工厂特性=>依赖注入–IOC=>AOP编程=>Spring事务=>纯注解开发。本文来自观看B站孙帅Spring教程后做的笔记。持续更新…