Java动态代理–反思1
问题的产生
今天早晨起来 闲来无事 就顺便看了下 之前的动态代理的 代码;发现生成代理对象的方法Object java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 其第二个参数是 一个CLass数组对象;我就想 原来放到是代理对象(经测试是 实现对象UserServiceImpl,非实现对象的接口UserService)实现的实现接口;能不能通过改变这个参数生成不同方法来 实现屏蔽 代理对象的一些方法;于是就产生了 接下来的修改及测试;
那么接下来上修改后的代码:
修改的面目全非的代码
接口部分 根据上述思路 多写了一个接口
接口一
package proxy.service;
/**
* 额外接口 用于实验 是否能通过往 newProxyInstance 传入 第二个接口数组参数 不同 来屏蔽一些代理对象的方法
* @author admin
*
*/
public interface AdditionalInterface {
void dance();
void sing();
}
接口二
package proxy.service;
/**
* 被代理对象接口
* @author admin
*
*/
public interface UserService {
void eat();
void speak();
}
实现部分
package proxy.service.impl;
import proxy.service.AdditionalInterface;
import proxy.service.UserService;
public class UserServiceImpl implements UserService,AdditionalInterface {
@Override
public void eat() {
System.out.println("吃饭中。。。");
}
@Override
public void speak() {
System.out.println("说话中。。。");
}
@Override
public void dance() {
System.out.println("跳舞中。。。");
}
@Override
public void sing() {
System.out.println("唱歌中。。。");
}
}
生成代理对象方法所在的类
package proxy.service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 切面类 合并 具有生成代理对象 的类
* @author admin
*
*/
public class MyRepect implements InvocationHandler{
private Object us ;
public MyRepect(Object us) {
super();
this.us = us;
}
public void before() {
System.out.println("前置方法");
}
public void after() {
System.out.println("后置方法");
}
//获取代理类 之所以要类类加载器参数 是 代理类 动态生成的 并没有class文件
public Object getUserService() {
return Proxy.newProxyInstance(us.getClass().getClassLoader(), new Class[] { UserService.class,AdditionalInterface.class }, this);
}
//交织 业务类 和 切面类
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object ret = method.invoke(us, args);
after();
return ret;
}
}
测试代码
package proxy.test;
import proxy.service.AdditionalInterface;
import proxy.service.MyRepect;
import proxy.service.UserService;
import proxy.service.impl.UserServiceImpl;
public class MainTest {
public static void main(String[] args) {
//获取被代理对象
Object us = new UserServiceImpl();
MyRepect myRepect = new MyRepect(us);
//执行 额外接口的方法
AdditionalInterface additionalInterface = (AdditionalInterface) myRepect.getUserService();
additionalInterface.sing();
System.out.println("---------------------------华丽的分割线---------------------------");
//执行原始接口的方法
UserService userService = (UserService) myRepect.getUserService();
userService.eat();
}
}
执行结果
思考及总结
1、通过上面的代码修改 可以在测试的地方强转成不同的 接口 然后去调用相应的方;感觉就和没有代理是一样的;当然不考虑公共业务的添加; 也从另外一个方面看出 方法newProxyInstance 第二个参数的作用 如果传入的参数 没有对应的接口 那么生成的代理对象是没有这个接口下面的方法的;也说明了 如果代理方法没有接口的话 无法使用这个代理类生成的工具;
2、感觉如果说按照我上面的思想 其实 MyRepect 应该根据 代理类 的不同方法 添加不同公共扩展 然后写成一个版本的 MyRepect; 但是后来我又想到一个问题 如果说 代理类所有方法要实现的公共扩展怎么办;难道还要在不同版本的MyRepect里面添加 代码吗? 这样不就降低了代码的复用率 ;感觉 实现类 实现的接口应该 是 一个继承了 上面例子 的两个接口 ; 如果 要给代理类所有方法 增加扩展就用 这个接口 ;如果分开的话 就按照上面的方式来; 下面我画了一个图 不知道能不能阐述清楚我的想法
最后 看着改后代码 ;感觉 还是有种不和谐的感觉;但又说不来;如果需要讨论可以下方留下评论,欢迎大家给予批评指正;Thanks♪(・ω・)ノ