您的位置:首页 > 编程语言 > Java开发

java静态代理和动态代理

2015-10-30 17:27 471 查看
1. java代理静态代理和动态代理:
静态代理
package onlyfun.caterpillar;

import java.util.logging.Level;
import java.util.logging.Logger;

public
class
HelloSperker {
private Logger
logger = Logger.getLogger(this.getClass().getName());

public
void
hello(String name){
//方法执行开始时留下记录
logger.log(Level.INFO,
"hello method starting ...");;

System.out.println("name: "+name);

//方法结束时留下记录
logger.log(Level.INFO,"hello method ending ...");

}
public
static void
main(String []args){
HelloSperkerhelloSperk=
new
HelloSperker();
helloSperk.hello("adu");
}
}
如果分析这段代码,当执行hello时在方法开始和结束都进行相应的记录,最简单的方法就是如上面使用日志动作,然而对于HelloSperker来说,日志的这几个动作并不属于它的业务逻辑,因此是给HelloSperker增加了额外的工作。
如果有大量的类似的程序,里面都需要进行与业务无关的日志记录、权限检查、事务管理等,而且如果要维护这些代码,如果仍然是这样写法,维护必要要耗费大量时间,负担不可谓不重啊。而且这样的代码,如果哪一天不需要相关的日志等服务了,那么修改也会让我们很痛苦。如何解决这样令我们痛苦的事情那?
一个好的方法就是使用代理proxy。代理可分为静态代理和动态代理。
静态代理:在静态代理中,代理对象与被代理对象必须实现同一个接口,在代理对象中可以实现日志等相关服务,并在需要的时候再调用被代理的对象,被代理对象当中就可以仅保留与业务相关的职责。
例子:
#Interface:IHello
package onlyfun.caterpillar;

public
interface
IHello {
public
void
hell(String name);
}
#Class:HelloSperker1 :implements IHello
package onlyfun.caterpillar;

public
class
HelloSperker1 implements IHello {

@Override
public
void
hell(String name) {
// TODO Auto-generated method stub
System.out.println("name:"+name);
}

}
#class:HelloProxy:implements IHello
package onlyfun.caterpillar;

import java.util.logging.Level;
import java.util.logging.Logger;

public
class
HelloProxy implementsIHello {
private Logger
logger = Logger.getLogger(this.getClass().getName());
private IHello
helloObject;
public HelloProxy(IHello
helloObject){
this.helloObject =
helloObject;
}
@Override
public
void
hell(String name) {
// TODO Auto-generated method stub
log("hello method starting ....");
helloObject.hell(name);
log("hello method ending ...");
}
public
void
log(String msg){
logger.log(Level.INFO,msg);
}
}
#StaticProxyTest
package onlyfun.caterpillar;

public
class
StaticProxyTest {

public
static void
main(String[]
args) {
// TODO Auto-generated method stub
IHellohelloObject =
new
HelloSperker1();
HelloProxyproxy=
new
HelloProxy(helloObject);
proxy.hell("along");
}

}
这里确实是将业务和与业务无关的内容分开了,比较之前确实是有较大改善,但是如果这样每个业务类都需要对应一个这样的proxy,那也是工作量巨大,有没有更好的方式那。
自己的说明:这里代理类可以不实现IHello接口,只不过在该代理类内部写一个一样的方法,即可,只不过不是实现,貌似也能实现效果。有点像设计模式里的门面模式(装饰模式)吧。
下面将动态代理:
在jdk1.3之后加入了可协助开发动态代理功能的API,使用动态代理,因此可以使用一个handler处理服务于各个对象,但是这个处理者的类handler必须实现java.lang.reflect.InvocationHandler接口。
具体的实现是:
package onlyfun.caterpillar;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;

public
class
LogHandler implementsInvocationHandler {
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);
}
//重写invoke方法(使用代理时每次操作都会执行的方法,实际上执行的是
//method.invoke,在它前后加上日志动作即可)
@Override
public Object invoke(Object
proxy, Method method, Object[]
args) throws Throwable {
// TODO Auto-generated method stub
Objectresult =
null;
try{
log("method starts: ....["+method+"]...");
result =
method.invoke(delegate,
args);
log("method end:...["+method+"]...");
}catch(Exception
e){
log(e.toString());

}
return
result;
}
public
void
log(String msg){
logger.log(Level.INFO,msg);
}
}
#动态代理测试
package onlyfun.caterpillar;

public
class
ProxyDemo {

public
static void
main(String[]
args) {
// TODO Auto-generated method stub
//初始化动态代理handler对象
LogHandlerlogHandler=
new
LogHandler();
//绑定需要被代理的对象实例,并返回一个代理对象,
IHello helloSperk = (IHello)logHandler.bind(new HelloSperker1());
//执行输出
helloSperk.hell("dudu");
}

}

这里可以看出LogHandler不在执行与特定的接口,这里根据指定的接口代替了原来静态代理中的实现接口的方式,从而达到通用。这种从单独设计,到使用静态代理,再到使用动态代理,逐层精进、业务独立,达到设计上的复用、可维护性的特征,正是设计的发展方向。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: