The dependency injection mechanism of spring allows you to configure required resources for components at runtime, without the need to compile component code.
This reduces the coupling between components to a considerable extent.
Spring uses the dependency injection mode to remove Dependencies from the encoding, which greatly reduces the coupling between components,
Implements plug-and-play in the true sense of the component. This is also one of spring's most valuable features.
IOC, in the vernacular, is the relationship between control programs by containers, rather than in non-traditional implementations, directly controlled by program code. This is also
That is, the concept of "control reversal": control is transferred from application code to external containers, and control is transferred.
Compared with IOC, "dependency injection" is indeed a more accurate description of this ancient and fashionable design concept. Understanding from the name,
The so-called dependency injection, that is, the dependency between components is determined by the container at runtime. In the image, the container dynamically changes a dependency
System injection into components.
A laptop is connected to a peripheral storage device through a pre-specified interface (USB). For a laptop,
Only the user-specified data is sent to the USB interface, and the path of the data is determined by the USB device currently connected. In the USB
Before the device is loaded, it is impossible for the laptop to predict which device the user will connect to on the USB interface.
The dependency between the slave nodes starts to form.
According to the above description about the dependency injection mechanism, at runtime (system boot, USB device loading ),
In Windows) to inject dependencies (laptops rely on USB devices for data access) into components (Windows
File Access component ).
This is a version of the dependency injection mode in the real world.
The purpose of dependency injection is not to bring more functions to the software system, but to improve the probability of Component Reuse and build the system.
A flexible and scalable platform. Compare the USB interface with the previous serial/parallel interface and PS2 interface, so we can understand what it means.
The dependency injection mechanism reduces the dependency between components and greatly improves the portability of components. This means that components are reused.
There will be more opportunities, and its injection mechanism at runtime is the key factor.
For example:
<Beans>
<Bean id = "datasource"
Class = "org. springframework. JNDI. jndiobjectfactorybean">
<Property name = "jndiname">
<Value> JAVA: COMP/ENV/jdbc/sample </value>
</Property>
</Bean>
<Bean id = "sampledao" class = "net. xiaxin. Spring. Dao. sampledao">
<Property name = "datasource">
<Ref local = "datasource"/>
</Property>
</Bean>
</Beans>
Datasource in sampledao will be dynamically injected by the container during runtime, and the specific configuration and initialization of datasource
It will also be completed by the container at runtime.
Compared with the traditional implementation method (for example, initializing datasource instances by coding), we can see that the system implementation based on dependency injection is similar
Flexible and concise.
By using the dependency injection mechanism, you only need to configure it in a simple way, and you can specify
Datasource instance. Sampledao only needs to use the datasource instance injected by the container to complete its own business logic, instead
Focus on where and who the specific resources come from.
In the above example, we assume that sampledao is a component running in a J2EE container (such as WebLogic ). During runtime
Obtain the datasource instance from the container through JNDI.
Now we assume that the deployment environment has changed and the system needs to run independently from the application server. As a result, container support is lost,
The method for obtaining datasource through JNDI is no longer valid. How do we modify it to adapt to the new system environment? It's easy, we
You only need to modify the datasource Configuration:
<Beans>
<Bean id = "datasource"
Class = "org. Apache. commons. DBCP. basicdatasource"
Destroy-method = "close">
<Property name = "driverclassname">
<Value> org. gjt. Mm. MySQL. Driver </value>
</Property>
<Property name = "url">
<Value> JDBC: mysql: // localhost/sample </value> </property>
<Property name = "username">
<Value> User </value>
</Property>
<Property name = "password">
<Value> mypass </value>
</Property>
</Bean>
<Bean id = "sampledao" class = "net. xiaxin. Spring. Dao. sampledao">
<Property name = "datasource">
<Ref local = "datasource"/>
</Property>
</Bean>
</Beans>
Here our datasource is provided by the Apache DBCP component. Without writing any code, we implement the datasource
Switch. Recall how much effort we need to make the same changes in the traditional encoding mode.
The dependency injection mechanism reduces the dependency between components and greatly improves the portability of components. This means that components are reused.
There will be more opportunities.
There are three methods of dependency injection: interface injection, constructor injection, and set injection. The most common and popular method is set injection and construct subinjection.
Advantages of constructing subinjection in type2:
1. "A complete and valid object is created during the construction period." For this Java design principle, type2 is undoubtedly the best
Responder.
2. Avoids tedious compilation of setter methods. All dependencies are set in the constructor and dependency relationships are displayed in a centralized manner,
Easier to read.
3. Because there is no setter method, the dependency is set at one time by the container during the construction. Therefore, after the component is created
It is relatively "unchanged" and does not need to worry about the dependency between the upper-Layer Code and the component by executing the setter method during the call process.
Damage occurs, especially for components in the singleton mode, which may have a significant impact on the entire system.
4. Similarly, since associations are expressed only in constructors, only the component creator needs to care about the dependencies within the component.
For callers, dependencies in components are in the black box. Shield unnecessary information from the upper layer, and
Level clarity provides a guarantee.
5. By constructing subinjection, we can determine the dependency injection sequence in the constructor. for a large number
For components that depend on external services, the order in which dependencies are obtained may be very important, for example, the order in which a dependency is injected
A prerequisite is that the datasource and related resources of the component have been set.
Advantage of setting value injection in type3
1. For programmers who are used to developing traditional JavaBean, it is more straightforward to set the dependency through the setter method.
More natural.
2. If the dependency (or inheritance relationship) is complex, the constructor in the type2 mode will also be quite large (we need
To set all dependencies in the constructor), The type3 mode is more concise.
3. Some third-party class libraries may require that our components provide a default constructor (such as struts
In this case, the dependency injection mechanism of the Type2 type reflects its limitations, and it is difficult to fulfill our expectations.
Yes.
To achieve non-invasive goals. Spring has introduced a large number of Java reflection mechanisms through dynamic
The calling method avoids the constraints of the hard encoding method, and establishes its Core Component beanfactory as its dependency injection.
Implementation Basis of the mechanism.
The Org. springframework. Beans package contains the implementation classes of these core components. The core is beanwrapper.
And beanfactory class. These two types are not technically complex, but they are critical for the Spring framework.
If you have time, we recommend that you study the source code.
Bean wrapper
The so-called dependency injection means that the container injects the dependency into the component at runtime.
In general, during runtime, spring will reference other objects according to the configuration file through the setter method provided by the component.
Row settings.
Let's see how to use spring beanwrapper to operate a JavaBean:
Object OBJ = Class. forname ("net. xiaxin. Beans. User"). newinstance ();
Beanwrapper BW = new beanwrapperimpl (OBJ );
Bw. setpropertyvalue ("name", "Erica ");
System. Out. println ("user name =>" + BW. getpropertyvalue ("name "));
Bean Factory is responsible for creating bean instances based on the configuration file. The following items can be configured:
1. Bean property values and dependencies (references to other beans)
2. Bean creation mode (whether to use Singleton mode, that is, whether to maintain globally unique instances only for the specified class)
3. Bean initialization and destruction methods
4. Bean dependency
The following is a complete bean configuration example:
<Beans>
<Description> spring bean configuration sample </description>
<Bean
Id = "theaction" (1)
Class = "net. xiaxin. Spring. Qs. upperaction" (2)
Singleton = "true" (3)
Init-method = "init" (4)
Destroy-method = "Cleanup" created
Depends-on = "actionmanager" plugin
>
<Property name = "message">
UE> Hello </value> quit
</Property>
<Property name = "DESC">
<Null/>
</Property>
<Property name = "datasource">
<Ref local = "datasource"/> metrics
</Property>
</Bean>
<Bean id = "datasource"
Class = "org. springframework. JNDI. jndiobjectfactorybean">
<Property name = "jndiname">
<Value> JAVA: COMP/ENV/jdbc/sample </value>
</Property>
</Bean>
</Beans>
The following code demonstrates how to obtain bean instances through beanfactory:
Inputstream is = new fileinputstream ("bean. xml ");
Xmlbeanfactory factory = new xmlbeanfactory (is );
Action action = (Action) Factory. getbean ("theaction ");
In combination with the above content about beanwrapper, we can see that beanwrapper implements attribute settings for a single bean.
Operation. Beanfactory is a management container for multiple beans. According to the given configuration file, beanfactory reads
Class Name, attribute name/value, and then bean loading and attribute setting through the reflection mechanism.
Applicationcontext
Beanfactory provides management functions for Java Beans, while applicationcontext provides a more framework-based
(As shown in the preceding example, beanfactory uses an API rather than the framework style ).
Applicationcontext covers all beanfactory functions and provides more features. In addition,
Applicationcontext provides more open implementation for integration with existing application frameworks (for example, for Web applications, we can
Configure applicationcontext in Web. XML ).
Compared with beanfactory, applicationcontext provides the following extensions:
1. International support
In the beans. xml file, we can define the language information (such as the prompt information) in the program
Information is extracted and defined in the configuration file, which provides great flexibility for us to convert different language versions of the application.
2. Resource Access
Supports access to files and URLs.
3. Event Propagation
The event propagation feature provides good support for detecting state changes in the system.
4. Load multiple instances
You can load multiple context instances in the same application.
For Web applications, Spring provides configurable
Applicationcontext loading mechanism.
Currently, the loader has two options: contextloaderlistener and contextloaderservlet. Both are fully functional.
Equivalent: it is implemented based on the listener interface introduced in servlet2.3, while the other is implemented based on the servlet interface.
You can select the target Web Container based on the actual situation.
The configuration is very simple. Add the following in Web. xml:
<Listener>
<Listener-class>
Org. springframework. Web. Context. contextloaderlistener
</Listener-class>
</Listener>
Or:
<Servlet>
<Servlet-Name> context </servlet-Name>
<Servlet-class>
Org. springframework. Web. Context. contextloaderservlet
</Servlet-class>
<Load-on-startup> 1 </load-on-startup>
</Servlet>
With the preceding configuration, Web containers automatically load/WEB-INF/applicationcontext. xml Initialization
For an applicationcontext instance, you can specify the location of the configuration file through context-Param:
<Context-param>
<Param-Name> contextconfiglocation </param-Name>
<Param-value>/WEB-INF/myapplicationcontext. xml </param-value>
</Context-param>
After the configuration is complete, you can use
Webapplicationcontextutils. getwebapplicationcontext
Method to obtain the applicationcontext reference in a web application.