Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reflection + spring dependency injection

I'm trying to understand if I can combine reflection with spring dependency injection as the following:

public interface ClientCommand {

    public void execute(...);

    public static enum Command {
        SomeCommand(SomeCommand.class);

        private Class<? extends ClientCommand> clazz;

        private Command(Class<? extends ClientCommand> clazz) {
            this.clazz = clazz;
        }

        public Class<? extends ClientCommand> getClazz() {
            return clazz;
        }

        public static ClientCommand getClientCommand(String name) {
            Command command = Enum.valueOf(Command.class, name);
            return command.getClazz().newInstance();
        }
    }
}

This will create an instance of a command class based on the name passed in getClientCommand. This is an example of class extending ClientCommand:

public class LoginCommand implements ClientCommand {
    @Autowired
    private UserRepository userRepository;

    public void setUserRepository(@Qualifier("userRepository")UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void execute(...) {
        ...
    }
}

And the repository is something like:

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    ....
}

When the LoginCommand.execute() method is executed, the UserRepository is null. If I use the newInstance() to create the object, does spring care at all to inject the dependencies? More than for practical use, is to understand if is theoretically possible to get this code working. Thanks in advance

like image 931
Ae. Avatar asked Sep 20 '11 22:09

Ae.


People also ask

Does Spring use reflection for dependency injection?

The Spring Framework does allow you to autowire private fields. You do see people doing this. And Spring will perform some reflection magic to perform dependency injection.

What is reflection in dependency injection?

Dependency Injection with Reflection Abathur deploys another strategy that allows the dependency injection to be hidden away from the user of the framework. Abathur can not predict the class name of the user implementation but it can cheat and look it up in the assembly.

Does Spring IOC use reflection?

Spring IoC container uses reflection internally to create instances and to do most of the stuff. And reflection API provides newInstance() methods to create objects.

What is reflection API in Spring?

Reflection is an API that is used to examine or modify the behavior of methods, classes, and interfaces at runtime.


2 Answers

To answer this question:

If I use the newInstance() to create the object, does spring care at all to inject the dependencies?

I will answer with no, not by default. Spring will only inject dependencies on objects that Spring is in control of, and if you are using reflection to instantiate it, or the new operator, then you are the one in control, not Spring.

But, there is hope. You can use AspectJ to do bytecode weaving when the new operator is used, or even when Class.newInstance() is used.

Take a look at this Spring documentation for more on this approach.

like image 163
nicholas.hauschild Avatar answered Oct 29 '22 05:10

nicholas.hauschild


Since you're creating the object on your own Spring will not do dependency injection on the object. It will also not add any AOP proxies for it if its configured to do that.

You can either use AspectJ to instrument your code by adding the logic necessary to do dependency injection on the instance. This is done completely transparently.

Or you can do it yourself by using AutowireCapableBeanFactory. It's a semi-internal interface that you can use and its intended for just this purpose. It has a set of methods that do various parts of creating and injecting, you'll probably need the createBean() method.

You can get an AutowireCapableBeanFactory by calling getAutowireCapableBeanFactory on your ApplicationContext.

In your case it would probably be a good idea to create a CommandFactory, make that implement ApplicationContextAware and have a method like createCommand() that calls createBean().

like image 28
sigget Avatar answered Oct 29 '22 03:10

sigget