Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create instance by interface using reflection?

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

When the program runs into

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

throws

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

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

like image 699
Yinc Avatar asked May 25 '26 20:05

Yinc


1 Answers

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<?>[]{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
    }
});

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.

like image 190
geanakuch Avatar answered May 28 '26 08:05

geanakuch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!