Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用反射通过接口创建实例?_Java_Spring_Reflection - Fatal编程技术网

Java 如何使用反射通过接口创建实例?

Java 如何使用反射通过接口创建实例?,java,spring,reflection,Java,Spring,Reflection,我正在尝试编写Spring的DI,只是一个简单的例子。有一个控制器,这个@AutoWired是我定义的空注释 public class UserController { @AutoWired private UserServise userServise;// a empty interface } 这是实现注释注入的代码: UserController userController = new UserController(); Class<? extends User

我正在尝试编写Spring的DI,只是一个简单的例子。有一个控制器,这个@AutoWired是我定义的空注释

public class UserController {
    @AutoWired
    private UserServise userServise;// a empty interface
}
这是实现注释注入的代码:

UserController userController = new UserController();
Class<? extends UserController> clazz = userController.getClass();

Stream.of(clazz.getDeclaredFields()).forEach(field -> {
    AutoWired annotation = field.getAnnotation(AutoWired.class);
    if (annotation != null) {
        field.setAccessible(true);
        Class<?> type = field.getType();
        try {
            Object o = type.getDeclaredConstructor().newInstance();
            field.set(userController, o);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});
投掷

java.lang.NoSuchMethodException: com.learning.servise.UserServise.<init>()
java.lang.NoSuchMethodException:com.learning.servise.UserServise.()

我猜程序找不到接口的构造函数,那么我如何为注入创建这个实例呢?

我不完全确定您想要实现什么。我假设
UserService
是一个接口? 如果是这样,则无法实例化。您必须选择一个实现接口的类。 因此,要么编写一个类(也可以是匿名类或lambda类),要么使用代理:

Object instance = Proxy.newProxyInstance(type.getClassLoader(),
     new Class<?>[]{type}, new InvocationHandler() {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //implement your methods here
        //determine which method you're in by checking the method arg
    }
});
Object instance=Proxy.newProxyInstance(type.getClassLoader(),
新类[]{type},新调用处理程序(){
@凌驾
公共对象调用(对象代理、方法、对象[]args)抛出Throwable{
//在这里实现您的方法
//通过检查方法arg确定您使用的方法
}
});
我不知道这是不是你想要的,但这是我最好的猜测

但也许你做错了。当您试图复制Spring时,有一个可以自动连接的组件或bean是很重要的。因此,您可能应该首先关注@Bean注释(或类似注释)。您可能需要某种类型的注册表,它可以提取带注释的bean,然后将它们注入到您的自动连接字段中。看来你把这件事前后颠倒了。
您应该首先将重点放在将bean注册到您的框架上,并且只有当您实现了这一点时,才应该尝试注入它们。

非常感谢您。我明白问题是什么。所以程序创建接口实例是不对的。我应该在Autowire之前完成Bean或其他基本注释。当然,您可以尝试找到接口的实现,然后实例化它们。但您无法控制使用哪种实现,哪种实现不好。而且,只有当实现类可以使用无参数构造函数构造时,这才有效。我认为最好允许用户决定在他的上下文中使用哪个实现。Spring检查实现自动连接接口的bean。如果找到一个实例,它将使用bean的实际类来创建实例
Object instance = Proxy.newProxyInstance(type.getClassLoader(),
     new Class<?>[]{type}, new InvocationHandler() {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //implement your methods here
        //determine which method you're in by checking the method arg
    }
});