软件开发原则
- 高内聚,低耦合
- 对修改关闭,对扩展开放(升级的话尽量不要修改原来的代码,可以重新编写一个实现类。)
没有使用面向接口编程会遇到这样的问题:按层开发,修改service中的某个方法的时候,会出现随便起名的问题,导致web中的代码都需要修改。用接口定义方法名就可以避免乱起名的问题了。
idea中从一个类中提取一个借口的方便方法
按下面的步骤即可提取:
工厂设计模式
步骤分析:
- 编写myBeans.xml 放在resources目录下
- 编写MyBeanFactory类
提供一个map集合
提供一个静态代码块
解析配置文件的操作,但是为了提高效率,配置文件只需要解析一次
实现应该将所有的对象都创建好,用的时候直接获取即可,可以使用map集合存这些内容,id为key,class属性对应的对象作为value.
调用getBean方法的时候,只需要通过id去map中找对应的对应即可。
代码实现:
编写myBeans.xml配置文件
<beans>
<bean id="userService" class="cn.itcast.service.impl.UserServiceImpl"/>
<bean id="addressService" class="cn.itcast.service.impl.AddressServiceImpl"/>
</beans>
编写MyBeanFactory工厂
public class MyBeanFactory{
private static Map<String,Object> map = new HashMap<>();
public static Object getBean(String id){
return map.get(id);
}
static{
try {
//使用dom4j解析配置文件mybeans.xml
InputStream is = MyBeanFactory.class.getClassLoader().getResourceAsStream("myBeans.xml");
SAXReader saxReader = new SAXReader();
Document doc = saxReader.read(is);
//获取到所有的bean标签 返回值:list (使用xpath)
List<Element> list = doc.selectNodes("//bean");
//遍历list,获取到每个bean标签,
for (Element element : list) {
//获取id属性值
String id = element.attributeValue("id");
//获取class属性值
String clazz = element.attributeValue("class");
//将id做为key,将class对应的对象为value存放到map中
Object obj = Class.forName(clazz).newInstance();
map.put(id,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
获取service对象
UserService userService = (UserService) MyBeanFactory.getBean("userService");
升级
目前是第一次调用MyBeanFactory.getBean方法的时候才会加载MyBeanFactory(执行静态代码块),假如这个配置文件特别大,里面放了大几千个类,第一次获取的时候有点慢.我们可以把解析配置文件和创建对象的操作提前.可以提前到项目初始化的时候.
怎么知道项目启动(项目初始化)了呢?web服务器启动每个项目成功之后,都会给每个项目创建一个ServletContext对象.ServletContext对象创建的时候就代表这项目启动成功了.
怎么知道ServletContext对象创建了?使用ServletContextListener监听器就可以了
创建一个监听器(ServletContextListener),在它的初始化方法中完成工厂对象的map集合的初始化操作即可
步骤:
- 创建一个类,实现ServletContextListener接口
- 在初始化方法中 加载myBeans.xml,调用MyBeanFactory.init(inputStream)完成工厂的初始化操作
- 在MyBeanFactory提供init方法即可
代码实现:
监听器:
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
//初始化方法
public void contextInitialized(ServletContextEvent sce) {
//加载mybean.xml
InputStream is = MyServletContextListener.class.getClassLoader().getResourceAsStream("myBeans.xml");
//调用MyBeanFactory.init(inputStream)
MyBeanFactory.init(is);
}
@Override
//销毁方法
public void contextDestroyed(ServletContextEvent sce) {
}
}
工厂类MyBeanFactory:
public class MyBeanFactory {
private static Map<String,Object> map = new HashMap<>();
public static Object getBean(String id){
return map.get(id);
}
public static void init(InputStream is) {
try {
//使用dom4j解析配置文件mybeans.xml
SAXReader saxReader = new SAXReader();
Document doc = saxReader.read(is);
//获取到所有的bean标签 返回值:list (使用xpath)
List<Element> list = doc.selectNodes("//bean");
//遍历list,获取到每个bean标签,
for (Element element : list) {
//获取id属性值
String id = element.attributeValue("id");
//获取class属性值
String clazz = element.attributeValue("class");
//将id做为key,将class对应的对象为value存放到map中
Object obj = Class.forName(clazz).newInstance();
map.put(id,obj);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("工厂初始化失败");
}
}
}
获取对象还是通过工厂获取,方便,升级维护就变得爽多了,这样就能追上软件快速发展的脚步了。