在FR的插件开发中,我们有时候可能会遇到这样一个问题
我们在实现一个接口方法时
public C Func( A a, B b );
接口方法里面操作后需要修改A的私有成员D d,为其修改或增加一些方法,以改变D类的一些FR的没有接口处理的功能。
为了更容易理解我抽象了一个场景
首先是我们的执行过程
- public class App {
- public static void main(String[]args){
- A a = new A("张三");
- IA e = new E();
- D d = new D(a);
- d.run();
- //其他操作
- e.run( d );
- //其他操作
- d.run();
- }
- }
复制代码- public class A {
-
- private String name = null;
-
- public A(){
-
- }
-
- public A(String name){
- this.name = name;
- }
-
- public void run() {
- System.out.println("A is "+name+" running.");
- }
-
- public void run2(){
- System.out.println("A.run2 is "+name+" running.");
- }
- }
复制代码- public class D{
-
- private A a = null;
-
- public D( A a ){
- this.a = a;
- }
-
- public void run() {
- a.run();
- }
- }
复制代码- public class E implements IA {
- @Override
- public void run( D d ) {
- System.out.println("E.run");
- }
- }
复制代码- public interface IA {
- public void run(D d);
- }
复制代码 我们运行显示结果为:
A is 张三 running.
E.run
A is 张三 running.
假设我们又一个需求是需要改变执行逻辑里面的第二次D.run时A的run逻辑。而类A和APP以及D是FR产品JAR包里面的业务逻辑,我们没办法重写。
我们能写的就是接口IA的实现E,怎么做呢?通过反射的方式实现,我封装了一个代理类。
- public class Proxy {
-
- public static <T> T getv( Object val, String key ){
- return Reflect.on(val).get(key);
- }
-
- public static void setv( Object val, String key, Object v ){
- Reflect.on(val).set(key,v);
- }
-
- public static void reset( Object val, String key, Object v ){
- Reflect ref = Reflect.on(val);
- copy(v,ref.get(key));
- ref.set(key, v);
- }
-
- public static <T> T copy( T target, Object old ){
- Reflect ref = Reflect.on(target);
- Reflect oref = Reflect.on(old);
- Set<String> kset = oref.fields().keySet();
- for(String fieldName : kset ){
- ref.set( fieldName, oref.get(fieldName) );
- }
- return target;
- }
- }
复制代码
我们先开发一个类B继承A,在B方法里面我们重新定义A的run逻辑
- public class B extends A {
-
- //修改方法
- public void run() {
- String name = Proxy.getv(this, "name");
- System.out.println("B is "+name+" running.");
- Proxy.setv(this,"name", "李四");
- run2();
- }
- //新增方法
- }
复制代码 然后我们在E中实现
- public class E implements IA {
- @Override
- public void run( D d ) {
- System.out.println("E.run");
- B b = new B();
- Proxy.reset(d, "a", b);
- }
- }
复制代码
运行结果如下
A is 张三 running.
E.run
B is 张三 running.
A.run2 is 李四 running.
第二次A的run逻辑就已经改成B的了~
这种方式虽然一定程度上能解决很多没有接口的插件问题,但是因为这种方式对FR类的封装破坏性很强,而且由于本身不是接口功能,FR自身在升级的时候可能不会被考虑到,而发生改变。所以不到万不得已最好别随便用~
编辑于 2018-5-17 22:31
|