代理模式之动态代理实践

         在前一篇博客中讲解了一些代理模式的基础知识,是否还记得它们的分类:静态代理和动态代理。那么它们到底怎么用呢?接下来就结合实战来体验一下动态代理的奥妙。

一、背景

       drp实现FlowCardManagerImpl的时候,刚开始每个方法的实现都有打开-提交-回滚-关闭事务的流程,但是Manager层的作用是实现业务逻辑,和事务的实现没有必然的联系,并且都是重复的代码。所以这里明显存在着问题,急需要将事务与Manager分离。那么怎么实现呢?答案就是用动态代理来实现。

二、准备

        Java中实现动态代理机制,必须做一些准备工作。即:需要java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy 类的支持

java.lang.reflect.InvocationHandler接口的定义如下
public interface InvocationHandler {
    public Object invoke(Object proxy,Method method, Object[] args) throws Throwable;
}

Object proxy:被代理的对象

Method method:要调用的方法

Object[] args:方法调用时所需要参数

java.lang.reflect.Proxy类的定义如下
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h) throwsIllegalArgumentException

CLassLoader loader:类的加载器

Class<?> interfaces:得到全部的接口

InvocationHandler h:得到InvocationHandler接口的子类的实例

三、实现

(一)采用动态代理封装事务

package com.bjpowernode.drp.util;
 
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.InvocationTargetException;
importjava.lang.reflect.Method;
importjava.lang.reflect.Proxy;
importjava.sql.Connection;
 
/**
 * 采用动态代理封装事务
 * TransactionHandler实现InvocationHandler接口,覆写invoke()方法
 * 代理事务的业务写在invoke()方法中
 * @author yujie
 *
 */
 
public classTransactionHandler implements InvocationHandler {
 
privateObject targetObject;
 
publicObject newProxyInstance(Object targetObject){
this.targetObject= targetObject;
 
//通过proxy直接创建动态代理类实例,
//targetObject.getClass().getClassLoader():类的加载器
      //targetObject.getClass().getInterfaces():得到全部的接口
//this:得到InvocationHandler接口的子类的实例,即invoke
returnProxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
}
 
 
    /**
    * Object proxy:被代理的对象
*Method method:要调用的方法
*Object[] args:方法调用时所需要参数
    */
publicObject invoke(Object proxy, Method method, Object[] args)
throwsThrowable {
Connectionconn = null;
Objectret = null;
try{
//从ThreadLocal中取得Connection
conn= ConnectionManager.getConnection();
if(method.getName().startsWith("add")||
method.getName().startsWith("del")||
method.getName().startsWith("modigy")){
//手动控制事务提交
ConnectionManager.beginTransaction(conn);
}
//调用目标对象的业务逻辑方法
ret= method.invoke(targetObject, args);
if(!conn.getAutoCommit()){
//提交事务
ConnectionManager.commitTransaction(conn);
}
}catch(ApplicationExceptione){
//回滚事务
ConnectionManager.rollbackTransaction(conn);
throwe;
}catch(Exceptione) {
e.printStackTrace();
if(einstanceof InvocationTargetException){
InvocationTargetExceptionete = (InvocationTargetException)e;
throwete.getTargetException();
}
//回滚事务
ConnectionManager.rollbackTransaction(conn);
thrownew ApplicationException("操作失败!");
}finally{
ConnectionManager.closeConnection();
}
returnret;
}
 
}<span style="font-family: SimSun; font-size: 14pt; "> </span>

(二)Servlet的调用

privateFlowCardManager flowCardManager;
@Override
publicvoid init(ServletConfig config) throws ServletException {
  flowCardManager =(FlowCardManager)getBeanFactory().getServiceObject(FlowCardManager.class);
     
  TransactionHandler transactionHandler = newTransactionHandler();
  flowCardManager =(FlowCardManager)transactionHandler.newProxyInstance(flowCardManager);
}
@Override
protectedvoid doGet(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
if(Constants.SHOW_ADD.equals(getCommand())) {
showAdd(request,response);
}elseif (Constants.ADD.equals(getCommand())) {
add(request,response);
}elseif (Constants.DEL.equals(getCommand())) {
del(request,response);
}elseif (Constants.MODIFY.equals(getCommand())) {
 
}else{        
search(request,response);        
}
}
 
@Override
protectedvoid doPost(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
doGet(request,response);
}
 
/**
 * 添加
 * @param request
 * @param response
 * @throws ServletException
 * @throws IOException
 */
privatevoid add(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
//供方分销商代码
StringclientId = request.getParameter("clientInnerId");
//需方客户代码
String[]aimIds = request.getParameterValues("aimInnerId");
//物料代码
String[]itemNos = request.getParameterValues("itemNo");
//操作数量
String[]qty = request.getParameterValues("qty");
 
FlowCardflowCard = new FlowCard();
//操作类型,
flowCard.setOpttype("A");
//取得会计核算期,正常情况下应该从session中取得
FiscalYearPeriodfiscalYearPeriod = new FiscalYearPeriod();
fiscalYearPeriod.setId(1);
flowCard.setFiscalYearPeriod(fiscalYearPeriod);
 
//分销商
Clientclient = new Client();
client.setId(Integer.parseInt(clientId));
flowCard.setClient(client);
//取得录入人
flowCard.setRecorder(getCurrentUser());
//操作日期
flowCard.setOptDate(newDate());
//单据状态
flowCard.setVouSts("N");
 
List<FlowCardDetail>flowCardDetailList = new ArrayList();
for(int i=0; i<aimIds.length; i++) {
FlowCardDetailflowCardDetail = new FlowCardDetail();
 
//需方客户
AimClientaimClient = new AimClient();
aimClient.setId(Integer.parseInt(aimIds[i]));
flowCardDetail.setAimClient(aimClient);
 
//物料
Itemitem = new Item();
item.setItemNo(itemNos[i]);
flowCardDetail.setItem(item);
 
//操作数量
flowCardDetail.setOptQty(newBigDecimal(qty[i]));
 
//调整标记
flowCardDetail.setAdjustFlag("N");
 
flowCardDetailList.add(flowCardDetail);
}
 
flowCard.setFlowCardDetailList(flowCardDetailList);
 
//                //通过工厂取得业务逻辑对象
FlowCardManagerflowCardManager =(FlowCardManager)getBeanFactory().getServiceObject(FlowCardManager.class);
flowCardManager.addFlowCard(flowCard);
 
response.sendRedirect(request.getContextPath()+ "/servlet/flowcard/FlowCardServlet?command=" + Constants.QUERY);
}<span style="font-size: 14pt; font-family: Calibri; "> </span>

(三)Manager的修改

<span style="font-size: 14pt;">/**
 * 流向单维护服务层实现
 * @author yujie
 *
 */
public classFlowCardManagerImpl implements FlowCardManager {
 
privateFlowCardDao flowCardDao;
 
publicFlowCardManagerImpl(){
this.flowCardDao= (FlowCardDao)BeanFactory.getInstance().getDaoObject(FlowCardDao.class);
}
@Override
publicvoid addFlowCard(FlowCard flowCard) throws ApplicationException {
 
try{
//生成流向单单号
StringflowCardVouNo = flowCardDao.generateVouNo();
//添加流向单主信息
flowCardDao.addFlowCardMaster(flowCardVouNo,flowCard);
//添加流向单明细信息
flowCardDao.addFlowCardDetail(flowCardVouNo,flowCard.getFlowCardDetailList());
}catch(DaoExceptione) {
thrownew ApplicationException("添加流向单失败!");
}        
}
}
</span><h2><span style="font-size:18px;">(四)Manager修改之前</span></h2><span style="font-size: 14pt;">/**
 * 流向单维护服务层实现
 * @author yujie
 *
 */
public classFlowCardManagerImpl implements FlowCardManager {
 
privateFlowCardDao flowCardDao;
 
publicFlowCardManagerImpl(){
this.flowCardDao= (FlowCardDao)BeanFactory.getInstance().getDaoObject(FlowCardDao.class);
}
 
@Override
publicvoid addFlowCard(FlowCard flowCard) throws ApplicationException {
Connectionconn=null;
try{
//取得connection
conn = ConnectionManager.getConnection();
 
//开启事务
ConnectionManager.beginTransaction(conn);
 
//生成流向单单号
StringflowCardVouNo = flowCardDao.generateVouNo();
//添加流向单主表信息
flowCardDao.addFlowCardMaster(flowCardVouNo,flowCard);
//添加流向单明细信息
flowCardDao.addFlowCardDetail(flowCardVouNo,flowCard.getFlowCardDetailList());
 
//提交事务
ConnectionManager.commitTransaction(conn);
}catch(DaoExceptione){
//回滚事务
ConnectionManager.rollbackTransaction(conn);
thrownew ApplicationException("添加流向单失败!");
}finally{
//关闭connection并从threadlocal中清楚
ConnectionManager.closeConnection();
}
}
}</span>

四、对比

                       

                                                                          无动态代理

                             

                                                                      用动态代理

       通过以上用了代理和没用代理的比较可以发现动态代理的巨大优点,它可以大大减少代码量,将其公共的代码封装为动态代理类,在程序运行的过程中判断到底用哪个具体的被代理对象,从而达到解耦的效果。

五、总结

        通过动态代理的利用,可以总结下动态代理的代理机制及特点:

        1.通过实现 InvocationHandler 接口创建自己的调用处理器;

        2.通过为 Proxy 类指定 ClassLoader对象和一组 interface来创建动态代理类;

        3.通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

        4.通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值