java - 子类传递变量给父类的问题
PHP中文网
PHP中文网 2017-04-17 14:50:33
0
1
295

j2EE,框架采用struts2,spring,hibernate,服务器端处理请求的顺序是action > service > dao .
因为所有对象的service都有增删改查操作,所以我们使用一个基类,然后所有的service类都继承这个基类,这个service基类的代码如下:

public class BaseServiceImpl<T, E>  {
    
    //the class of the bean's dao .
    public T  dao ;

    //save object
    public boolean set( E obj ) {
        if ( dao==null ) return false;    //@1
        if ( obj==null ) return true;
        
        try {
            Class clazz = dao.getClass();
            Method method = clazz.getMethod( "save" , obj.getClass() );    //@2
            //clazz.getDeclaredMethod(name, parameterTypes)
            boolean R = (Boolean)  method.invoke( dao , (Object) obj );
            return R;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } 
    }

}

下面给出service类的代码,他继承自 BaseServiceImpl :

@Component("abnormalListManage")
public class FreightCenter_abnormalListManageImpl <E> extends BaseServiceImpl<FreightCenter_abnormalListDao,FreightCenter_abnormalList> implements FreightCenter_abnormalListManage,reflectData  {
    @Resource(name="abnormalListDao") 
    private FreightCenter_abnormalListDao listDao;
        
    public FreightCenter_abnormalListManageImpl() {
        super.dao = listDao;
    }
    
}

**同样的dao类也有基类,然后每个dao类都继承自这个基类
dao基类的代码如下:**

public class BaseDaoImpl<T, E> {
    
    //SessionFactory for create session 
    public SessionFactory sessionFactory = null;    
    //the class of the bean's manage
    public T manage = null;
    
    public boolean save( E obj ) {
        //do sth.
    }
    
}

dao类代码如下:

@Transactional
@Component("abnormalListDao")
public class FreightCenter_abnormalListDaoImpl extends BaseDaoImpl<FreightCenter_abnormalListManage, FreightCenter_abnormalList> implements FreightCenter_abnormalListDao{
    @Resource
    private SessionFactory sessionFactory;
    
    @Resource( name="abnormalListManage" )
    private FreightCenter_abnormalListManage abnormalListManage;
    
    public FreightCenter_abnormalListDaoImpl() {
        super.sessionFactory = sessionFactory;
        super.manage = abnormalListManage;
    }
}

现在问题来了,当我们执行service类的set方法时,set方法里面的语句:
if ( dao==null ) return false; //在 service 基类 BaseServiceImpl 里面,标注为@1
在这个语句中,成员变量 dao 是 null 值,个人分析如下:
service类 FreightCenter_abnormalListManageImpl 是由spring来管理,他是在服务器运行时初始化的
初始化这个类时运行了构造方法,构造方法中将ListDao传递给基类的变量 dao ,但是这个时候 ,listDao肯定是null,因为spring肯定是在类初始化完成后才给ListDao赋值!
为了解决这个问题,我们在service类里面重写了set方法
修改后,service类的实现类代码如下:

@Component("abnormalListManage")
public class FreightCenter_abnormalListManageImpl <E> extends BaseServiceImpl<FreightCenter_abnormalListDao,FreightCenter_abnormalList> implements FreightCenter_abnormalListManage,reflectData  {
    @Resource(name="abnormalListDao") 
    private FreightCenter_abnormalListDao listDao;
    
    public FreightCenter_abnormalListManageImpl() {
        super.dao = listDao;
    }
    public boolean set( FreightCenter_abnormalList obj ) {    //重写set方法
        super.dao = listDao;
        return super.set( obj );
    }
}

这样就解决了上面的问题 .

但是,另外的问题出现了,当执行到语句( 使用@2来标注 ):

  • Method method = clazz.getMethod( "save" , obj.getClass() );
    boolean R = (Boolean) method.invoke( dao , (Object) obj );*
    时报错,save方法不存在!

我现在的问题是:
1 在service类里面,如果我不重写set方法,如何将变量listDao的值传递给service基类?我希望是在service类初始化之后传递,如何解决?如果可以,我就不用重写那么多方法了,因为我还有好多方法需要重写.
2 为什么反射调用dao类的save方法时会报错?难道继承自基类(父类)的方法不属于本类的方法?

PHP中文网
PHP中文网

认证高级PHP讲师

全員に返信(1)
黄舟

最初の質問

問題の核心はここにあります:

 public FreightCenter_abnormalListManageImpl() {
        super.dao = リストダオ;
    }

メソッド内で構築されているため、listDao には値が割り当てられていないため、super.daonull である必要があります。しかし、コードを見てみると、listDao に値を割り当てる場所が見つかりません。super.dao と同期する必要があるのは、 に値を割り当てるときだけです。 >listDao に値を割り当てるだけです。一般に、setListDao() メソッドが必要です。このメソッドを変更するだけで済みます。

public void setListDao(FreightCenter_abnormalListDao dao) {
    super.dao = リストDao = dao;
}

2 番目の質問

@wanlion 自身の回答を引用します (読みやすいようにここに記載します)

リフレクションが dao クラスの save メソッドを呼び出すとエラーが発生するのはなぜですか? メソッドはこのクラスのメソッドではなく、基本クラス (親クラス) から継承されたものなのでしょうか?
答えは「いいえ」です。

問題の理由は、リフレクションを呼び出すときに、指定されたメソッドのパラメータの型が間違っているためです。

メソッド method = clazz.getMethod( "save" , obj.getClass() );
boolean R = (Boolean) method.invoke( dao , (Object) obj );

次のように変更する必要があります:

メソッドメソッド = clazz.getMethod( "save" , Object.class );
boolean R = (Boolean) method.invoke( dao , (Object) obj );

2 番目の質問の改善

現在のコードに関する限り、リフレクションを避けるためのインターフェイスを追加するだけで済みます。

インターフェイス BaseDao<E>
    ブール値保存(E obj);
}

クラス BaseServiceImpl<E>
    //Bean の dao のクラス。
    // ここで、Dao と E の関係はインターフェイスを通じて確立されます
    // したがって、反映せずに後で直接 save を呼び出すことができます
    パブリック BaseDao<E>

    //オブジェクトを保存
    public boolean set( E obj ) {
        if ( dao == null ) は false を返します。 //@1
        if ( obj == null ) は true を返します。

        試す {
            // 反射を取り除く
            dao.save(obj) を返します。
        } catch (例外 e) {
            e.printStackTrace();
            false を返します。
        }
    }
}

クラス BaseDaoImpl は BaseDao を実装します。
    //セッション作成用のSessionFactory
    // テストコードにSessionFactoryが定義されていないため、この文をコメントアウトします。
    // public SessionFactory sessionFactory = null;
    //Bean の管理クラス
    パブリック T 管理 = null;

    public boolean save( E obj ) {
        // TODOは実装されていません
        false を返します。
    }
}

上記のコードはファイル内にあるため、正常にコンパイルされます。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート