插件开发技巧之暴力重写

楼主
我是社区第55902位番薯,欢迎点我头像关注我哦~
在FR的插件开发中,我们有时候可能会遇到这样一个问题
我们在实现一个接口方法时
public C Func( A a, B b );
接口方法里面操作后需要修改A的私有成员D d,为其修改或增加一些方法,以改变D类的一些FR的没有接口处理的功能。
为了更容易理解我抽象了一个场景
首先是我们的执行过程
  1. public class App {
  2.         public static void main(String[]args){
  3.                 A a = new A("张三");
  4.                 IA e = new E();
  5.                 D d = new D(a);
  6.                 d.run();
  7.                 //其他操作
  8.                 e.run( d );
  9.                 //其他操作
  10.                 d.run();
  11.         }
  12. }
复制代码
  1. public class A {
  2.    
  3.     private String name = null;
  4.    
  5.     public A(){
  6.         
  7.     }
  8.    
  9.     public A(String name){
  10.         this.name = name;
  11.     }
  12.    
  13.     public void run() {
  14.         System.out.println("A is "+name+" running.");
  15.     }
  16.    
  17.     public void run2(){
  18.         System.out.println("A.run2 is "+name+" running.");
  19.     }
  20. }
复制代码
  1. public class D{
  2.         
  3.         private A a = null;
  4.         
  5.         public D( A a ){
  6.                 this.a = a;
  7.         }
  8.         
  9.         public void run() {
  10.                 a.run();
  11.         }

  12. }
复制代码
  1. public class E implements IA {

  2.         @Override
  3.         public void run( D d ) {
  4.                 System.out.println("E.run");
  5.         }
  6. }
复制代码
  1. public interface IA {
  2.         public void run(D d);
  3. }
复制代码
我们运行显示结果为:
A is 张三 running.
E.run
A is 张三 running.

假设我们又一个需求是需要改变执行逻辑里面的第二次D.run时A的run逻辑。而类A和APP以及D是FR产品JAR包里面的业务逻辑,我们没办法重写。
我们能写的就是接口IA的实现E,怎么做呢?通过反射的方式实现,我封装了一个代理类。
  1. public class Proxy {
  2.        
  3.         public static <T> T getv( Object val, String key ){
  4.                 return Reflect.on(val).get(key);
  5.         }
  6.        
  7.         public static void setv( Object val, String key, Object v ){
  8.                 Reflect.on(val).set(key,v);
  9.         }
  10.        
  11.         public static void reset( Object val, String key, Object v ){
  12.                 Reflect ref = Reflect.on(val);
  13.                 copy(v,ref.get(key));
  14.                 ref.set(key, v);
  15.         }
  16.        
  17.         public static <T> T copy( T target, Object old ){
  18.                 Reflect ref = Reflect.on(target);
  19.                 Reflect oref = Reflect.on(old);
  20.                 Set<String> kset = oref.fields().keySet();
  21.                 for(String fieldName : kset ){
  22.                         ref.set( fieldName, oref.get(fieldName) );
  23.                 }
  24.                 return target;
  25.         }       
  26. }
复制代码


我们先开发一个类B继承A,在B方法里面我们重新定义A的run逻辑
  1. public class B extends A {
  2.         
  3.         //修改方法
  4.         public void run() {
  5.                 String name = Proxy.getv(this, "name");
  6.                 System.out.println("B is "+name+" running.");
  7.                 Proxy.setv(this,"name", "李四");
  8.                 run2();
  9.         }
  10.         //新增方法
  11. }
复制代码
然后我们在E中实现
  1. public class E implements IA {

  2.         @Override
  3.         public void run( D d ) {
  4.                 System.out.println("E.run");
  5.                 B b = new B();
  6.                 Proxy.reset(d, "a", b);
  7.         }
  8. }
复制代码


运行结果如下
A is 张三 running.
E.run
B is 张三 running.
A.run2 is 李四 running.

第二次A的run逻辑就已经改成B的了~

这种方式虽然一定程度上能解决很多没有接口的插件问题,但是因为这种方式对FR类的封装破坏性很强,而且由于本身不是接口功能,FR自身在升级的时候可能不会被考虑到,而发生改变。所以不到万不得已最好别随便用~








编辑于 2018-5-17 22:31  
分享扩散:

沙发
发表于 2018-5-18 07:56:02
一脸蒙蔽,趴不力克死待体克哇哦的买恩。。。。
板凳
发表于 2018-5-18 08:35:59
不明觉厉
地板
发表于 2018-5-18 09:20:23
师傅这种技术我啥时候能达到啊
5楼
发表于 2018-5-18 11:24:51
6楼
发表于 2018-5-18 12:29:25
不明嚼栗~
7楼
发表于 2018-5-18 18:06:23
8楼
发表于 2018-5-18 22:31:58
来自手机
这是传说中的天书吗
9楼
发表于 2018-5-20 13:43:07
楼主发帖,必须懵逼出去
10楼
发表于 2018-6-15 08:39:21
mark.
11楼
发表于 2018-11-8 11:45:08
牛批牛批,飞鞋点金
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

12回帖数 3关注人数 9748浏览人数
最后回复于:2018-11-8 11:45

返回顶部 返回列表