关于Java静态代理模式的实现
2011年03月01日
在java中有两类代理模式,动态代理模式和静态代理模式,关于动态代理的实现,涉及到字节码的重新编写,无法单纯的通过java代码实现,不过jdk内置实现了动态代理模式,基于接口的,其它的有cglib,aspectJ等,这里不献丑了.
之所以有动态代理的出现,主要是因为静态代理不够灵活,这里相对传统的静态代理模式进行一下改进,使我们能方便快捷的使用代理的设计思想,同时有不需要大量冗余的代码.
话不多说,先看一个传统的代理模式的实现:
//接口
public interface HelloService {
void sayHello(String name);
}
//接口实现
public class HelloSerivceImpl implements HelloService{
@Override
public void sayHello(String name) {
Console.writeLine("Hi~,glad to meet U,"+name);
}
}
//代理实现
public class HelloServiceProxy implements HelloService{
private HelloService service;
public HelloServiceProxy(HelloService service){
this.service=service;
}
@Override
public void sayHello(String name) {
Method m=service.getClass().getDeclaredMethod("sayHello", String.class);
this.before(service, m, new Object[]{name});
service.sayHello(name);
this.before(service, m, new Object[]{name});
}
public void after(Object target, Method method, Object[] params) {
System.out.println(">>>>>>after the method of " + method.getName());
}
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName());
}
}
//测试
static void test_static(){
HelloService service=new HelloServiceProxy(new HelloSerivceImpl());
service.sayHello("lining");
}
从上面我们可以看,代理的接口实现实际上是调用接口实例的对应方法,并且在其执行之前调用before方法,在执行后调用after方法,从而实现拦截器的效果.但是当接口的方法很多的时候,我们需要对每个方法重复上面的过程,这将充满重复的代码段,增加我们的工作量,为此我们又必须对其进行改造和优化.
从上面我们可以看出,代码重复的地方在于before和after方法,而且两个方法是分开的,能想到的一个简单的改进方法就是将方法名作为参数传递过去,进行调用,于是我们这里抽象出来一个统一执行的方法:
public class HelloServiceProxy implements HelloService {
private HelloService service;
public HelloServiceProxy(HelloService service) {
this.service = service;
}
@Override
public void sayHello(String name) {
invoke("sayHello", name);
}
public void after(Object target, Method method, Object[] params) {
System.out.println(">>>>>>after the method of " + method.getName());
}
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName());
}
private Object invoke(String name, Object... params) {
Object result = null;
try {
Class[] types = new Class[params.length];
for (int i = 0; i >>>>>after the method of " + method.getName());
}
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName());
}
private Object invoke(Object... params) {
Object result = null;
String methodName = MethodTool.getCallerMethodName(1);
try {
Class[] types = new Class[params.length];
for (int i = 0; i [] types = new Class[args.length];
for (int i = 0; i >>>>>after the method of " + method.getName());
}
@Override
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName()); }
});
} //测试方法
static void test_static(){
HelloService service=new HelloServiceProxy(new HelloSerivceImpl());
service.sayHello("lining");
}
好了,我的关于静态代理模式的实现就是这样,以后实现代理的时候,只需继承静态代理的基类和代理对象的接口,对于接口中的方法实现中统一调用proxy方法即可.暂时能够优化的程度就到这了,如果进一步优化,恐怕需要动态改写字节码了,研究过javaassit的,可以考虑用它实现.
第一次发帖,如果哪里有错,欢迎批评指正,莫要拍砖!
2011年03月01日
在java中有两类代理模式,动态代理模式和静态代理模式,关于动态代理的实现,涉及到字节码的重新编写,无法单纯的通过java代码实现,不过jdk内置实现了动态代理模式,基于接口的,其它的有cglib,aspectJ等,这里不献丑了.
之所以有动态代理的出现,主要是因为静态代理不够灵活,这里相对传统的静态代理模式进行一下改进,使我们能方便快捷的使用代理的设计思想,同时有不需要大量冗余的代码.
话不多说,先看一个传统的代理模式的实现:
//接口
public interface HelloService {
void sayHello(String name);
}
//接口实现
public class HelloSerivceImpl implements HelloService{
@Override
public void sayHello(String name) {
Console.writeLine("Hi~,glad to meet U,"+name);
}
}
//代理实现
public class HelloServiceProxy implements HelloService{
private HelloService service;
public HelloServiceProxy(HelloService service){
this.service=service;
}
@Override
public void sayHello(String name) {
Method m=service.getClass().getDeclaredMethod("sayHello", String.class);
this.before(service, m, new Object[]{name});
service.sayHello(name);
this.before(service, m, new Object[]{name});
}
public void after(Object target, Method method, Object[] params) {
System.out.println(">>>>>>after the method of " + method.getName());
}
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName());
}
}
//测试
static void test_static(){
HelloService service=new HelloServiceProxy(new HelloSerivceImpl());
service.sayHello("lining");
}
从上面我们可以看,代理的接口实现实际上是调用接口实例的对应方法,并且在其执行之前调用before方法,在执行后调用after方法,从而实现拦截器的效果.但是当接口的方法很多的时候,我们需要对每个方法重复上面的过程,这将充满重复的代码段,增加我们的工作量,为此我们又必须对其进行改造和优化.
从上面我们可以看出,代码重复的地方在于before和after方法,而且两个方法是分开的,能想到的一个简单的改进方法就是将方法名作为参数传递过去,进行调用,于是我们这里抽象出来一个统一执行的方法:
public class HelloServiceProxy implements HelloService {
private HelloService service;
public HelloServiceProxy(HelloService service) {
this.service = service;
}
@Override
public void sayHello(String name) {
invoke("sayHello", name);
}
public void after(Object target, Method method, Object[] params) {
System.out.println(">>>>>>after the method of " + method.getName());
}
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName());
}
private Object invoke(String name, Object... params) {
Object result = null;
try {
Class[] types = new Class[params.length];
for (int i = 0; i >>>>>after the method of " + method.getName());
}
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName());
}
private Object invoke(Object... params) {
Object result = null;
String methodName = MethodTool.getCallerMethodName(1);
try {
Class[] types = new Class[params.length];
for (int i = 0; i [] types = new Class[args.length];
for (int i = 0; i >>>>>after the method of " + method.getName());
}
@Override
public void before(Object target, Method method, Object[] params) {
System.out.println(">>>>>>before the method of " + method.getName()); }
});
} //测试方法
static void test_static(){
HelloService service=new HelloServiceProxy(new HelloSerivceImpl());
service.sayHello("lining");
}
好了,我的关于静态代理模式的实现就是这样,以后实现代理的时候,只需继承静态代理的基类和代理对象的接口,对于接口中的方法实现中统一调用proxy方法即可.暂时能够优化的程度就到这了,如果进一步优化,恐怕需要动态改写字节码了,研究过javaassit的,可以考虑用它实现.
第一次发帖,如果哪里有错,欢迎批评指正,莫要拍砖!