java 动态代理 2

想要掌握AOP的编程思想,首先应该对Java的动态代理机制有所了解,下面我结合一个例子,探讨一下java的动态代理机制
如果在执行某些方法时留下日志信息,凭直觉,可能会这样写
public class HelloSpeaker {
private Logger logger=Logger.getLogger(this.getClass().getName());
public void helllo(String name)
{
logger.log(Level.INFO, "hello method starts...");
System.out.println("Hello, "+name);
logger.log(Level.INFO, "hello method ends...");
}
}
对于HelloSpeaker类来说,日志的这几个动作并不属于HelloSpeaker业务逻辑,这使得此类增加了额外的职责。很可能程序中这种动作到处都有,使得维护日志程序代码难度加大。
另一方面,上面写法在不再需要日志,那么将需要修改所有留下日志动作的程序代码。
所以有了代理机制。
首先看下静态代理。在静态代理中,代理和被代理对象必需实现同一个接口。在代理对象中实现日志等服务,在被代理对象中实现业务相关内容。代理对象在需要时调用被代理对象。
例如,首先定义一个IHello接口
public interface IHello {
public void hello(String name);
}
其次,定义业务逻辑类并实现上述接口
public class HelloSpeaker2 implements IHello {
public void hello(String name) {
// TODO Auto-generated method stub
System.out.println("Hello, "+name);
}
}
再次,实现代理对象类,同样要实现IHello接口
public class HelloProxy implements IHello {
private IHello helloObject;
private Logger logger=Logger.getLogger(this.getClass().getName());
public HelloProxy(IHello helloObject)
{
this.helloObject=helloObject;
}

public void hello(String name) {
// TODO Auto-generated method stub
log("hello method starts...");
helloObject.hello(name);
log("hello method ends...");

}
private void log(String msg)
{
logger.log(Level.INFO,msg);
}
}
最后,编写一个测试程序。
public class TestProxy {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HelloSpeaker hs=new HelloSpeaker();
hs.helllo("TANLEI");
IHello proxy=new HelloProxy(new HelloSpeaker2());
proxy.hello("TANLEI");


}
}

从静态代理案例可以看到,代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每种方法进行代理,静态代理就无法胜任了,由此引出动态代理机制。
JDK1.3之后引入了动态代理功能的API,不必为特定对象与方法编制特定的代理对象。使用动态代理,可以使得一个处理者(handler)服务于各个对象。
首先,一个处理者的类必需实现InvocationHandler接口,
public class LogHandler implements InvocationHandler {
private Logger logger=Logger.getLogger(this.getClass().getName());
private Object delegate;
public Object bind(Object delegate)
{
this.delegate=delegate;
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object result=null;
logger.log(Level.INFO,"method starts");
result=method.invoke(delegate, args);
logger.log(Level.INFO,"method ends");
return result;
}
}
这段代码真的很难理解,所以我昨天学习了一下Java的反射机制,不过现在还是似懂非懂。。。大意是:使用 Proxy.newProxyInstance()静态方法建立一个代理对象,建立对象时必需告诉要代理的接口,之后操作所代理的对象。每次操作时执行invoke()方法,它会传入被代理对象的方法名称与执行参数,实际上要执行的方法会交由method.invoke(),在method.invoke()前后加上日志动作,method.invoke()方法传回的对象是实际方法执行后的回传结果。
其次,要实现动态代理,必需定义所要代理的接口,例如:
public interface IHello {
public void hello(String name);
}
然后让实现业务逻辑的HelloSpeaker类实现接口
public class HelloSpeaker implements IHello {
public void hello(String name) {
// TODO Auto-generated method stub
System.out.println("Hello, "+name);
}
}
最后编写测试程序
public static void main(String[] args) {
// TODO Auto-generated method stub
HelloSpeaker hs=new HelloSpeaker();
hs.helllo("TANLEI");
IHello proxy=new HelloProxy(new HelloSpeaker2());
proxy.hello("TANLEI");
LogHandler logHandler=new LogHandler();
IHello helloProxy=(IHello)logHandler.bind(new HelloSpeaker2());
helloProxy.hello("PIZI");
}
LogHandler不再服务于特定对象与接口,而HelloSpeaker也不用插入任何有关日志的动作。。。
总结:
(1)通过动态代理,实现了针对多种类型的对象进行统一的日志服务。使用时,只需绑定被代理的对象即可。。。
(2)运用了java的反射机制,我终于理解了反射机制的作用
有个问题我不太明白。。。动态代理中的invoke()方法在什么时候进行执行?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值