为什么我会想到使用模板方法呢?
在日常开发中,我们经常需要使用编程式事务来解决一些实在的业务问题。以Hibernate框架为例(其实对于ORM框架来说,都大同小异。我们公司使用的是Hiberante,所以这里就以Hibernate为例了),我们实现一个编程式事务如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | SessionFactory sessionFactory = (SessionFactory) applicationContext.getBean( "sessionFactory" ); Session session = sessionFactory.openSession(); try { session.beginTransaction(); String sql = "update table set A = :a where id = :id" ; session.createNativeQuery(sql) .setParameter( "a" , "a" ) .setParameter( "id" , id) .executeUpdate(); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); } finally { session.close(); } |
我们看上述的代码是不是有一种很乱的感觉,还要自己去写try{}catch{}finally{}。而且当我们代码中有很多地方都应用了编程式事务的话,那么我们的代码会显得有些臃肿。尤其对于我这种强迫症患者来说,哈哈!!
既然如此,我们肯定要想一种方式去优化一下,至少让它看起来更优美一些。我这里选择使用模板方法来改造一下。
什么是模板方法设计模式?
模板方法说白了就是将一段代码模板化,将通用的代码段抽取出来,并提供一些自定义的接口去定制的特定位置的某些业务功能。
根据我的理解,模板方法的核心思想就是 重写 。我们在模板中的指定位置提供一个外部可编辑的接口,让调用者可以根据需求去随意重写这个接口来达到他的目的。
其实在Spring中也广泛使用的模板方法,当我们学习Spring源码的时候会发现,实际上Bean的生命周期中就使用了模板方法。我们可以根据自己的需求在Bean生命周期的各个阶段去做一些事情。
代码优化
首先我们先维护一个抽象的模板类,这个类里包含了三个公开的方法,用来提供为调用者去定制使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public abstract class TransactionManagerTemplate { /** * 处理事务中的实际要处理的业务代码 */ public void handle() {} /** * 异常处理 */ public void exceptionHandle() {} /** * finally处理 */ public void finallyHandle() {} } |
然后我们创建一个事务管理器,封装一个runTransaction方法,里面就包含了上面那边不忍直视的代码。然后我们将Session和抽象的模板类作为参数传入
并且将抽象的模板类中的三个公开方法填入到try{}catch{}finally{}中的各个位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | @Component public class TransactionManager { @Autowired private ApplicationContext applicationContext; /** * 默认SessionFactory */ public static final String DEFAULT_SESSION_FACTORY = "sessionFactory" ; /** * 执行事务 * @param session * @param transactionManagerTemplate * * 使用案例: * Session session = transactionManager.getSession(); * transactionManager.runTransaction(session, new TransactionManagerTemplate() { * // 实际要重写的接口 * }); */ public void runTransaction(Session session, TransactionManagerTemplate transactionManagerTemplate) { try { session.beginTransaction(); transactionManagerTemplate.handle(); session.getTransaction().commit(); } catch (Exception e) { transactionManagerTemplate.exceptionHandle(); session.getTransaction().rollback(); } finally { transactionManagerTemplate.finallyHandle(); session.close(); } } /** * 获取默认SessionFactory * @return */ public SessionFactory getSessionFactory() { return getSessionFactory(DEFAULT_SESSION_FACTORY); } /** * 获取指定SessionFactory * @param beanName 指定SessionFactory的BeanName * @return */ public SessionFactory getSessionFactory(String beanName) { SessionFactory sessionFactory = (SessionFactory) applicationContext.getBean(beanName); if (sessionFactory == null ) { throw new BAPException( "不存在BeanName为【{}】的SessionFactory" , beanName); } return sessionFactory; } /** * 获取默认Session * @return */ public Session getSession() { return getSessionFactory(DEFAULT_SESSION_FACTORY).openSession(); } /** * 获取指定SessionFactory下的Session * @param sessionFactoryBeanName 指定SessionFactory的BeanName * @return */ public Session getSession(String sessionFactoryBeanName) { return getSessionFactory(sessionFactoryBeanName).openSession(); } } |
我们在业务代码中想要再次使用编程式事务时,就可以通过如下方式调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Session session = transactionManager.getSession(); transactionManager.runTransaction(session, new TransactionManagerTemplate() { @Override public void handle() { // try中要添加的业务逻辑 } @Override public void exceptionHandle() { // catch中要添加的业务逻辑 } @Override public void finallyHandle() { // finally中要添加的业务逻辑 } }); |
看,这是不是更美观了一些呀!
以上就是浅析Java模板方法的一种使用方式的详细内容,更多关于Java模板方法的资料请关注IT俱乐部其它相关文章!