【问题标题】:Java Reflection How to instantiate class field typeJava反射如何实例化类字段类型
【发布时间】:2018-08-05 22:17:28
【问题描述】:

我有一个跟随类,我试图通过反射实例化,然后自动实例化它的字段'databaseService'

@Controller
public class BaseController {

        @AutoInstantiate
        private DatabaseService databaseService;

        @AfterSetup
        public void initialize() {

                System.out.println("Testing " + databaseService.getEntry());

        }
    }

我正在尝试自动实例化的简单类

public class DatabaseService {

    public DatabaseService() {}

    public String getEntry() {

        return "I'm working! ";
    }
}

我想做什么

public class Instantiator {

    private static void start() {

        Reflections reflections = new Reflections("com");
        Class<?> clazz = reflections.getTypesAnnotatedWith(Controller.class)[0];

         //Assume 'clazz' is 'BaseController' (the parent class of DatabaseService)

        for(Field field : clazz.getDeclaredFields()) {

            if(field.isAnnotationPresent(AutoInstantiate.class)) {

                try {

                    field.setAccessible(true);

                    Object autowiredObject = field.getType().newInstance();

                    //HERES WHERE IT ALWAYS FAILS
                    field.set(clazz, autowiredObject);

                }
                catch(Exception e) {

                    logger.severe("Failure invoking class " + clazz.getName() + " Problem : " + e.getMessage());
                }
            }
        }
    }
}

还有简单的主要

public class App {

    public static void main(String[] args) throws Exception {

        Instantiator.start();
    }
}

问题 严重:调用类 com.controller.BaseController 失败问题:无法将 com.service.DatabaseService 字段 com.controller.BaseController.databaseService 设置为 java.lang.Class

总体问题: 我不确定如何让实例化类 Object (DatabaseService) 设置回它的父类 (BaseController)

【问题讨论】:

  • 您需要为该 set 方法提供对象实例,而不是字段类型。
  • @GotoFinal 感谢您的回复。我尝试了几种方法,但仍然无法使其正常工作。你能简单地告诉我那会是什么样子吗?非常感谢
  • 看看 IoC 容器是如何工作的。
  • 除非有BaseController 对象,否则无法实例化对象字段。
  • @zhh 为了读者的方便,我删除了一些代码行。我更新了上面的代码。假设这里的“clazz”是 BaseController

标签: java reflection


【解决方案1】:

这是您的问题所在:

field.set(autowiredObject.getClass(), autowiredObject);

查看documentation 获取Field.set(Object, Object) 方法的参数。我引用了一段:

参数:

obj - 应该修改其字段的对象

value - 被修改的 obj 字段的新值

(如果该字段是静态的,则应该将 obj 放置为 null)。

这意味着您实际上应该将与clazz具有相同类型的目标实例作为Field.set(Object, Object)方法中的第一个参数,因为您尝试修改字段的目标实例不是Class DatabaseService 的对象。但是,您丢失了一个带有 ControllerBaseController 注释的任何类型的实例,正如您稍后修改的那样。

【讨论】:

  • 如果不显式调用“BaseController”就不可能做到这一点吗?我希望在引入其他类型时通用地这样做
  • 您也可以通过反射创建该类型,但最后您需要该实例,否则它会如何工作?
  • @stackoverflow 根据您的情况,我认为您希望创建任何使用 Controller 注释的类也会自动创建 DatabaseService 并将其存储在字段 databaseService 中。您不能这样做,因为您无法检测到可执行文件的调用,换句话说,构造函数或方法。我建议您使用字段 databaseService 使 Controller 成为一个抽象类,并在构造函数中为 databaseService 分配一个新实例。所以任何继承 Controller 的人都会在实例化他们的类型时自动分配 databaseService 字段。
  • @RcExtract 感谢您的帮助和建议。非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-03
  • 2012-12-16
  • 2020-07-10
  • 1970-01-01
相关资源
最近更新 更多