—笔记总结来自孙哥说Spring5
EJB(Enterprise Java Bean)是重量级的框架,存在问题:
它可以涉及解决Java开发的每一层问题,而struts2, mybatis 只解决某一层问题。
整合设计模式
设计模式
概念:通过工厂类,创建对象。
//我们传统使用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 接口,实现接口里面的内容,然后在配置文件里修改下配置类名即可。
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.返回对象
}
配置文件applicationContext.properties.java
#userService = com.gogogo.UserServiceImpl
userDAO = com.gogogo.UserDAOImpl
//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 完整代码如下。
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");
总结- 通用工厂的使用方式
Spring核心是工厂设计模式,解藕合。Spring为我们提供的工厂,命名为 ApplicationContext, 配置文件是application.xml。
学习开心❤️
加加油~