问题
Does anyone know what technique spring uses to achieve dependency injection at runtime? Does it simply use aspects (AOP) or is it something more complicated?
回答1:
Spring does a lot of things, but dependency injection itself is actually a surprisingly simple mechanism.
It starts with having a registry for classes that are available for injection. Classes that are added to this registry are examined using reflection. A DI framework will look for relevant annotations and constructors to determine how to construct instances of the classes and also what other dependencies these classes may need.
The registry also keeps track of already created instances so they can be re-used. Re-using instances involves scoping, which determines when an instance can be re-used. With singletons (the default for Spring) instances can be re-used without restriction.
To create an instance of class with dependencies, reflection is used to create an instance. If there are any dependencies required, those are created first (if not already created) potentially triggering a lot of recursive creation of instances. If any of the dependencies cannot be created or there are multiple possible candidates, the framework can throw an exception to indicate a problem in your configuration.
A simple example, let's say we have an Injector
class that acts as both registry of classes and as a means to create new instances.
We register a few classes:
injector.register(Database.class);
injector.register(EmployeeDao.class);
Let's assume the Database class has no further dependencies, and EmployeeDao has a dependency on Database:
class EmployeeDao {
@Inject Database db;
}
The injector
, by means of reflection, knows that EmployeeDao
has a dependency on Database
. When we ask the injector
for an instance of EmployeeDao
the following happens:
EmployeeDao employeeDao = injector.getInstance(EmployeeDao.class);
1) A check is done if there already exists an instance of EmployeeDao
, if so it is returned.
2) If not, a check is done to see what is needed to construct EmployeeDao
, in this case it needs a Database
. The injector
calls itself recursively with:
Database database = injector.getInstance(Database.class);
2a) Again a check is done if an instance of Database
is already available.
2b) There are no further dependencies required in order to construct Database
so the injector
calls Database.class.newInstance()
and keeps track of it.
2c) A Database
instance is returned.
3) With the Database
instance available, the injector
can now construct the EmployeeDao
: EmployeeDao.class.newInstance()
-- with the help of reflection, the field database
is injected with the Database
instance.
4) The EmployeeDao
instance, now fully injected, is returned.
This is fairly direct way of obtaining an instance of a class, however this is at the core how DI frameworks like Spring work. More advanced features require creation of dynamic proxies and the use of AOP, but DI itself boils down to using reflection to construct instances automatically.
来源:https://stackoverflow.com/questions/43514699/how-does-spring-achieve-dependency-injection-at-runtime