设计模式的应用-工厂方法实现3层模型解耦
2017-02-23 19:50
507 查看
在web应用中常见的3层架构:控制层(Controller)、业务逻辑(Service)、数据持久层(DAO),控制层调用业务逻辑层,业务逻辑层调用数据层。
这样:
)
解耦,变成这样:
首先新建DAO工厂类
然后在业务逻辑层实现类中,注入Dao对象,如下:
遵循开闭原则,新建DAO实现类,只需要工修改厂类即可。
注:可以给DAO实现类添加自定义注解的方式,然后DAO工厂类通过反射,扫描出有指定注解的类,进行注入。
注意多线程问题:
Dao层和Service层均为“实际单例”缓存到map中,Service中持有dao成员变量,Servlet控制层持有service成员变量,由于Dao的使用的数据库连接来自于ThreadLocal变量,所以是线程安全的类,service只持有线程安全的类对象,所以也是线程安全的,同理上推。
然而,在我使用mybatis的过程中,出现了错误!提示“Executor 已经关闭”,mybatis官方资料显示mapper和sqlSession具有同样的声明周期,均是线程不安全的。此时对象之间的关系是Servlet包含service变量,service变量持有mapper对象,mapper对象对应的sqlSession会在一次请求后关闭(一个线程执行后), 此时再次执行会提示类时数据库连接以及关闭的问题!!!
在过滤器中关闭的SqlSession:
这样:
)
解耦,变成这样:
首先新建DAO工厂类
dao.factory.DaoFactory, 用于创建DAO对象:
/** * dao工厂 * * 注意:工厂类会在类加载的时候为每种DAO只会创建一个dao对象,所以DAO实现类中 * 不能通过对象包含数据库连接,应该通过ThreadLoacl<Connection>实现每线程一个连接 * @author * */ public class DaoFactory { /* 保存所有的Dao对象 */ private static final HashMap<Class<?>,Object> DAO_MAP = new HashMap<>(); static { try { init(); } catch(Exception e) { // 日志记录 } } private static void init() { DAO_MAP.put(ManagerDao.class, new ManagerDaoImpl()); DAO_MAP.put(OrderDao.class, new OrderDaoImpl()); DAO_MAP.put(SchoolDao.class, new SchoolDaoImpl()); DAO_MAP.put(UserDao.class, new UserDaoImpl()); } @SuppressWarnings("unchecked") public static<T> T getDao(Class<T> clazz) { // 注:clazz类对应的对象不存在,应该抛出异常 return (T) DAO_MAP.get(clazz); } }
然后在业务逻辑层实现类中,注入Dao对象,如下:
/** * 用户服务类 */ public class UserServiceImpl implements UserService { // 通过工厂方式注入 private UserDao userDao = DaoFactory.getDao(UserDao.class); ... }
遵循开闭原则,新建DAO实现类,只需要工修改厂类即可。
注:可以给DAO实现类添加自定义注解的方式,然后DAO工厂类通过反射,扫描出有指定注解的类,进行注入。
注意多线程问题:
Dao层和Service层均为“实际单例”缓存到map中,Service中持有dao成员变量,Servlet控制层持有service成员变量,由于Dao的使用的数据库连接来自于ThreadLocal变量,所以是线程安全的类,service只持有线程安全的类对象,所以也是线程安全的,同理上推。
然而,在我使用mybatis的过程中,出现了错误!提示“Executor 已经关闭”,mybatis官方资料显示mapper和sqlSession具有同样的声明周期,均是线程不安全的。此时对象之间的关系是Servlet包含service变量,service变量持有mapper对象,mapper对象对应的sqlSession会在一次请求后关闭(一个线程执行后), 此时再次执行会提示类时数据库连接以及关闭的问题!!!
在过滤器中关闭的SqlSession:
/** * 系统服务过滤器 * 过滤字符编码 * @author * */ public class OESServiceFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); try{ chain.doFilter(req, resp); }finally{ // 关闭SqlSession MybatisUtil.closeSqlSession(); } } @Override public void init(FilterConfig config) throws ServletException { } }
相关文章推荐
- 设计模式:浅析 抽象工厂、工厂方法、简单(静态)工厂 java实现
- 设计模式实践-反射到所有接口实现类实践工厂方法,页面中有大量计算数据时设计实践
- 设计模式:浅析 抽象工厂、工厂方法、简单(静态)工厂 java实现
- C++设计模式——工厂方法及工厂方法的隐藏实现(qq空间背景的例子)
- python实现的工厂方法--设计模式初级
- 使用单例和工厂设计模式实现dao实现层的解耦
- [设计模式]两种方法实现简单工厂模式
- 设计模式之三:工厂方法模式—多态工厂的实现
- 设计模式利剑一--工厂方法模型
- python实现工厂方法设计模式
- 23种设计模式之python实现--工厂方法
- 设计模式在游戏中的应用--工厂方法(五)
- 设计模式-工厂方法设计模式与接口的应用
- JAVA学习--接口的应用:工厂方法的设计模式
- Nutz 设计模式应用 --- 静态工厂方法
- Nutz 设计模式应用 --- 工厂方法
- scala实现设计模式之工厂方法模式
- GOF23设计模式之工厂方法模式的实现
- 设计模式 - 工厂方法(Factory Method) C++实现
- 追MM与设计模式的JAVA实现-简单工厂方法