—笔记总结来自孙哥说Spring5
引言
EJB(Enterprise Java Bean)是重量级的框架,存在问题:
- 运行环境苛刻
- 代码移植性差
所以称EJB是重量级框架。
什么是Spring?
Spring 是一个轻量级的框架.
- 它整合了多种设计模式,使开发环境更方便。
- 对运行环境没有额外要求
开源, Tomcat resion jetty
收费, weblogic websphere - 代码移植性高
不需要实现额外接口
Spring 开发
它可以涉及解决Java开发的每一层问题,而struts2, mybatis 只解决某一层问题。
整合设计模式
- 工厂
- 代理
- 模版
- 策略
设计模式
- 广义定义:面向对象设计中,解决特定问题的经典代码。
- 狭义定义:GOF4人帮定义的23种设计模式。
(工厂、适配器、装饰器、门面、代理、模版…)
工厂设计模式
什么是工厂设计模式?
概念:通过工厂类,创建对象。
//我们传统使用new创建对象形式:
User user = new User();
UserDAO userDAO = new UserDAO();
好处:解藕。
藕合: 是指代码块间强关联关系,一个地方改变,其他很多地方需要跟着改变,不利于代码间的维护。
出现耦合如下,新建一个接口,需要对相关代码进行修改,此时就比较麻烦,尤其是对大工程。
package com.gogogo;
public class Test {
public static void main(String[] args) {
//UserService userService = new UserServiceImplnew();
UserService userService = new UserServiceImpl();
userService.login("asds", "asds");
User user = new User("asds", "123456");
userService.register(user);
}
}
创建工厂类进行解藕
创建BeanFactory.java 文件
package com.gogogo;
public class BeanFactory {
public static UserService getUserService(){
return new UserServiceImpl();
}
}
在test文件中通过BeanFactory.getUserService()得到UserService对象,此时就在test文件中解藕了。
package com.gogogo;
public class Test {
public static void main(String[] args) {
//UserService userService = new UserServiceImplnew();
//UserService userService = new UserServiceImpl();
UserService userService = BeanFactory.getUserService();
userService.login("asds", "asds");
User user = new User("asds", "123456");
userService.register(user);
}
}
但是,我们在BeanFactory里又引入了藕合,因为是new 的对象。
怎么解决呢?
我们知道 对象的创建方式有两种方式:
- 直接调用构造方法,创建对象。
UserService userService = new UserServiceImpl();
- 通过反射的形式,创建对象,解耦合
Class clazz = Class.forName("com.gogogo.UserServiceImpl");
UserService userService =(UserService) clazz.newInstance();
所以, 解决方法如下:
package com.gogogo;
public class BeanFactory {
public static UserService getUserService(){
// return new UserServiceImpl();
UserService userService = null;
try {
Class clazz = Class.forName("com.gogogo.UserServiceImpl");
userService =(UserService) clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return userService;
}
}
反射加配置文件解藕
只通过反射,实现完全解决藕合 有点难,字符串还是需要再次改,此时不能通过一次反射解决问题,我们可以通过配置properties文件 对这个字符串进行解藕,如下:
Class clazz = Class.forName("com.gogogo.UserServiceImpl");
在resources文件夹下创建applicationContext.properties.java配置文件,名字可以自取。
#properties集合来存储 properties文件内容
#是特殊的Map, key = String value = String
#properties[userService] = com.gogogo.UserServiceImpl
#Properties.getProperty("userService)
userService = com.gogogo.UserServiceImpl
BeanFactory.java 文件修改如下:
package com.gogogo;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
private static Properties env = new Properties(); //创建properties集合
//IO在Java操作当中是一个系统级资源,一般尽量避免重复性打开,最好在程序启动的时候一次性打开读取内容
//使用静态代码块读取内容
static{
//第一步,获取IO流
InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
//第二步,文件中封装Properties集合中key=userService value=com.gogogo.UserServiceImpl
try {
env.load(inputStream);
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static UserService getUserService(){
// return new UserServiceImpl(); //藕合
UserService userService = null;
try {
//Class clazz = Class.forName("com.gogogo.UserServiceImpl"); //此处的字符串也是有耦合的
Class clazz = Class.forName(env.getProperty("userService"));
userService =(UserService) clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return userService;
}
}
此时,工厂类里就没有藕合了,通过反射和配置文件一起实现了解藕。
若有一天不满意 UserServiceImpl 这个实现类 ,想用一个更好的实现方式,那么就不需要改变现有代码,只新增实现类文件UserServiceImplNewOne,让它取实现UserService 接口,实现接口里面的内容,然后在配置文件里修改下配置类名即可。
配置简单的工厂类实例过程
1. 在BeanFactory.java里定义方法,主要是4步。
public static UserDAO getUserDAO(){
UserDAO userDAO = null; //1.创建对象
Class clazz = null;
try {
clazz = Class.forName(env.getProperty("userDAO"));//2.反射获取类
userDAO=(UserDAO) clazz.newInstance();//3.实例化赋值
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return userDAO; //4.返回对象
}
2. 在properties里配置好路径(包名+类名)
配置文件applicationContext.properties.java
#userService = com.gogogo.UserServiceImpl
userDAO = com.gogogo.UserDAOImpl
3. 创建对象 - 完全解藕
//private UserDAO userDAO = new UserDAOImpl(); //藕合
private UserDAO userDAO = BeanFactory.getUserDAO(); //解藕,配置BeanFactory和properties文件
}
通用工厂
由之前的代码配置,我们可以看出BeanFactory.java 里面由大量重复性代码,所以需要整改代码。
减少代码冗杂,编写通用生产类
整改如下
//通用工厂
//key 配置文件中key(即userService, userDAO)
public static Object getBean(String key){
Object ret = null;
try{
Class clazz = Class.forName(env.getProperty(key));
ret = clazz.newInstance();
}catch (Exception e){
e.printStackTrace();
}
return ret;
}
BeanFactory.java 完整代码如下。
- IO读取配置文件
- 通用工厂设计
public class BeanFactory {
private static Properties env = new Properties(); //创建properties集合
//IO在Java操作当中是一个系统级资源,一般尽量避免重复性打开,最好在程序启动的时候一次性打开读取内容
//使用静态代码块读取内容
static{
//第一步,获取IO流
InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
//第二步,文件中封装Properties集合中key=userService value=com.gogogo.UserServiceImpl
try {
env.load(inputStream);
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//通用工厂-解决方案如下
//key 配置文件中key(即userService, userDAO)
public static Object getBean(String key){
Object ret = null;
try{
Class clazz = Class.forName(env.getProperty(key));
ret = clazz.newInstance();
}catch (Exception e){
e.printStackTrace();
}
return ret;
}
}
获取 反射创建的对象:
//返回值是Object类,需强转
UserService userService = (UserService) BeanFactory.getBean("userService");
UserDAO userDAO = (UserDAO) BeanFactory.getBean("userDAO");
总结- 通用工厂的使用方式
- 定义类型(定义类)
- 通过配置文件的配置告知工厂,做相应配置(原来是通过new创建对象,由藕合)key = value
- 通过工厂获取类的对象,主要强转类型
总结
Spring核心是工厂设计模式,解藕合。Spring为我们提供的工厂,命名为 ApplicationContext, 配置文件是application.xml。
学习开心❤️
加加油~