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

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讲师

reply all(1)
黄舟

First question

The key to the problem is here:

    public FreightCenter_abnormalListManageImpl() {
        super.dao = listDao;
    }

Because it is constructed in the method, listDao has not been assigned a value, so super.dao must be null. But looking through the code, I can't find where you assign a value to listDao. You just need to assign a value to listDao synchronously when assigning a value to super.dao. Generally speaking, you should have a setListDao() method, you just need to change this method

public void setListDao(FreightCenter_abnormalListDao dao) {
    super.dao = listDao = dao;
}

Second question

Quoting @wanlion’s own answer (put here for easy reading)

Why does an error appear when calling the save method of the dao class through reflection? Are methods inherited from the base class (parent class) not methods of this class?
The answer is: No

The reason for the problem is that when calling reflection, the parameter type of the specified method is wrong, so:

Method method = clazz.getMethod( "save" , obj.getClass() );
boolean R = (Boolean) method.invoke( dao , (Object) obj );

should be changed to:

Method method = clazz.getMethod( "save" , Object.class );
boolean R = (Boolean) method.invoke( dao , (Object) obj );

Improvements regarding the second question

As far as the current code is concerned, you only need to add an interface to avoid reflection

interface BaseDao<E> {
    boolean save(E obj);
}

class BaseServiceImpl<E>  {
    //the class of the bean's dao .
    // 这里通过接口建立了 Dao 与 E 的关系
    // 所以后面可以直接调用 save 而不需要反射
    public BaseDao<E> dao ;

    //save object
    public boolean set( E obj ) {
        if ( dao == null ) return false;  //@1
        if ( obj == null ) return true;

        try {
            // 去掉反射
            return dao.save(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

class BaseDaoImpl<T, E> implements BaseDao<E> {
    //SessionFactory for create session
    // 注释掉这句因为测试代码里没有定义 SessionFactory
    // public SessionFactory sessionFactory = null;
    //the class of the bean's manage
    public T manage = null;

    public boolean save( E obj ) {
        // TODO not implemented
        return false;
    }
}

The above code compiles successfully. Because it is in a file, public

is not added.
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!