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

huangapple go评论56阅读模式
英文:

How to create instance by interface using reflection?

问题

我在尝试编写Spring的依赖注入(DI)代码,只是一个简单的示例。这里有一个控制器,而这个@AutoWired是我定义的一个空注解。

这是实现注解注入的代码部分:

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();
        }
    }
});

当程序执行到

Object o = type.getDeclaredConstructor().newInstance();

时,抛出了

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

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

英文:

I'm trying coding Spring's DI , just a simple example. There is a controller, and this @AutoWired is a Empty Annotation defined by me.

public class UserController {
    @AutoWired
    private UserServise userServise;// a empty interface
}

This is the code that implement Annotation injection:

UserController userController = new UserController();
Class&lt;? extends UserController&gt; clazz = userController.getClass();

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

When the program runs into

Object o = type.getDeclaredConstructor().newInstance();

throws

java.lang.NoSuchMethodException: com.learning.servise.UserServise.&lt;init&gt;()

I guess program cannot find a constructor for a interface, So how can I create this instance for the injection?

答案1

得分: 2

我并不完全确定您想要实现什么。我假设UserService是一个接口?
如果是这样,它不能被实例化。您必须要么编写一个实现该接口的类,要么使用代理:

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在这里实现您的方法
        // 通过检查方法参数来确定您在哪个方法中
    }
});

不确定这是否是您想要的,但这是我最好的猜测。

但也许您的方法不对。当您试图复制Spring时,重要的是您需要一个可以自动装配的组件或bean。因此,您可能首先应该专注于使用@Bean注解(或类似的注解)。您可能需要一种注册机制,可以捕获带有注解的bean,并将它们注入到自动装配的字段中。您似乎是在本末倒置。
您应该首先专注于将bean注册到您的框架中,只有在实现了这一点之后,才应尝试进行注入。

英文:

I am not completely sure what you are trying to achieve. I'm assuming that UserService is an interface?
If so it cannot be instantiated. You must either a class which implements the interface.
So either write a class (can also be anonymous or lambda) or use a proxy:

Object instance = Proxy.newProxyInstance(type.getClassLoader(),
     new Class&lt;?&gt;[]{type}, new InvocationHandler() {

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

Don't know if this is what you're after, but it is my best guess.

But maybe you're going at this wrong. When you're trying to replicate Spring, it is important that you have a component or bean you can autowire. So you should probably focus on your @Bean annotation (or similar) first. You'd want some sort of registry which picks up annotated beans and then injects them into your Autowired fields. It seems you have this back-to-front.
You should first focus on registering beans to your framework and only when you have achieved that you should try to inject them.

huangapple
  • 本文由 发表于 2020年9月30日 17:01:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/64134250.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定