小米手头上有个任务,需要在做某个业务之前做下鉴权。小米心想这个任务简单,只需要在原来的代码中加上鉴权的处理就可以了。
原来的代码是这样的:
package main.java;
/**
* <一句话功能简述>
* <功能详细描述>
*
* @author cKF54238
* @version [版本号, Apr 1, 2013]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public interface BusinessTrans
{
void doIt();
}
package main.java.impl;
import main.java.BusinessTrans;
/**
* <一句话功能简述>
* <功能详细描述>
*
* @author cKF54238
* @version [版本号, Apr 1, 2013]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class BusinessTransImpl implements BusinessTrans
{
/**
* 需求:希望在执行这个方法前,做一个Id鉴权
* @param name
*/
public void doIt()
{
System.out.println("excute immediatly");
}
}
这样只要在原来代码实现中加上鉴权的方法就行了。
package main.java.impl;
import main.java.BusinessTrans;
/**
* <一句话功能简述>
* <功能详细描述>
*
* @author cKF54238
* @version [版本号, Apr 1, 2013]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class BusinessTransImpl implements BusinessTrans
{
/**
* 需求:希望在执行这个方法前,做一个Id鉴权
* @param name
*/
public void doIt()
{
if (haveNoPopedom())
{
return;
}
System.out.println("excute immediatly");
}
private boolean haveNoPopedom()
{
return false;
}
}
这样小米舒舒服服的过了一个迭代,功能实在太简单了,三下五除二就搞定了,过了一个迭代,老大只会小米说,上一轮的功能又有点新的需求。小米心想这样简单的功能点一人天就可以搞定了,这一轮还可以做点别的东西。看了一下规格,一下就蒙了,凡是实现这个接口的都需要做鉴权。。。小米心中一声次奥想起了。
小米默默的将所有实现这个接口的类全部做了修改,然后测试了所有的功能,ok了。心想:靠,这么简单的功能,代码都是一样的,竟然花了我这么长时间。
迭代快接近尾声了,小米又没有时间做点别的了。。。。
很快下个迭代有开始了,老大又找小米,说这个功能又有点需求,小米赶紧看了下,心想千万不要和上次来一样的变态需求。看完后心凉了一般,需求是这样的,在做完doIt后,在做一下其他的事,同样是实现该死的接口的所有类。这一回,小米受不了了,他决定和同事们讨论下这个到底应该怎么玩?
同事A说:其实不需要修改原来的代码,在原来的实现类上面包一层,在这个包的一层中实现鉴权等其他事。
package main.java.impl;
import main.java.BusinessTrans;
import main.java.logger.Level;
import main.java.logger.Logger;
/**
* <一句话功能简述>
* <功能详细描述>
*
* @author cKF54238
* @version [版本号, Apr 1, 2013]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class BusinessTransProxy implements BusinessTrans
{
private BusinessTrans businessTrans;
public BusinessTransProxy(BusinessTrans businessTrans)
{
this.businessTrans = businessTrans;
}
public void doIt()
{
Logger.logging(Level.INFO, "before excute doIt");
businessTrans.doIt();
Logger.logging(Level.INFO, "after excute doIt");
}
}
这样凡是实现这个接口的所有的类就可以通过这个类,实现增加鉴权等一些列的功能。小米听到这个想法后,顿时觉得自己之前做的全部都是体力活。一阵欢喜之后,老大突然提出了一个问题:
如果同样有一个接口,含有一个doIt的方法,同样也需要做这样事呢?
同事B立马说道,“我再写一个这样的Proxy类实现他就行了嘛,这个方法果然好用”。
“那如果有一百个这样的接口都需要做这样的事呢?”
“这个,这个。。。。写一百个这个实现?”
“那还不是一个体力活?”
小米心想,“老大就喜欢给大家泼冷水,有一百个的时候再说嘛!”但是小米已经意识到肯定还有其他的一些方法。
其实现在的Jdk中提供了一个API java.lang.reflect.InvocationHandler的类.。这个类可以让我们在JVM调用某个类的方法时动态的为些方法做些什么事。
/*
* 文 件 名: DynaProxyBusinessTrans.java
* 版 权: * 描 述: <描述>
* 修 改 人: cKF54238
* 修改时间: Apr 1, 2013
* 跟踪单号: <跟踪单号>
* 修改单号: <修改单号>
* 修改内容: <修改内容>
*/
package main.java.dynaproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import main.java.logger.Level;
import main.java.logger.Logger;
/**
* <一句话功能简述>
* <功能详细描述>
*
* @author cKF54238
* @version [版本号, Apr 1, 2013]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class DynaProxyBusinessTrans implements InvocationHandler
{
/**
** 要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象)
*/
private Object delegate;
public Object bind(Object delegate)
{
this.delegate = delegate;
return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(),
this.delegate.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
Object result = null;
try
{
//执行原来的方法之前记录日志
Logger.logging(Level.DEBUGE, method.getName() + " Method start .");
result = method.invoke(this.delegate, args);
//执行原来的方法之前记录日志
Logger.logging(Level.DEBUGE, method.getName() + " Method end .");
}
catch (Exception e)
{
}
return result;
}
}
/*
* 文 件 名: AOPTest.java
* 版 权:
* 描 述: <描述>
* 修 改 人: cKF54238
* 修改时间: Apr 1, 2013
* 跟踪单号: <跟踪单号>
* 修改单号: <修改单号>
* 修改内容: <修改内容>
*/
package main.java.test;
import main.java.BusinessTrans;
import main.java.dynaproxy.DynaProxyBusinessTrans;
import main.java.impl.BusinessTransImpl;
/**
* <一句话功能简述>
* <功能详细描述>
*
* @author cKF54238
* @version [版本号, Apr 1, 2013]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class AOPTest
{
/**
* test
* @param args [参数说明]
*
* @return void [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static void main(String[] args)
{
// BusinessTrans businessTrans = new BusinessTransProxy(
// new BusinessTransImpl());
//
// businessTrans.doIt();
//
// BusinessTrans otherBusinessTrans = new BusinessTransProxy(
// new BusinessTransOtherImpl());
//
// otherBusinessTrans.doIt();
BusinessTrans BusinessTrans = (BusinessTrans) new DynaProxyBusinessTrans().bind(new BusinessTransImpl());
BusinessTrans.doIt();
}
}
这样不管是什么接口,都可以这么玩了。
小米看完这些后,高高兴兴的全部都回滚了,然后使用新学的这一招去修改了。可想而知,他仅仅花了一小会的时间就将代码全部搞好,调测完,真是太爽了。