Spring can effectively organize objects at various layers of J2EE applications. Whether it is the action object of the control layer, the service object of the business layer, or the DaO object of the persistence layer, it can be organically coordinated and run under the management of spring. Spring organizes objects at different layers in a loosely coupled manner. Action objects do not need to care about the specific implementation of service objects, and service objects do not need to care about the specific implementation of persistence layer objects, object calls at each layer are completely interface-oriented. When the system needs to be restructured, the amount of code rewriting will be greatly reduced.
All of the above mentioned have to be adapted to the core mechanism of spring and dependency injection. Dependency injection organizes beans and beans together by configuration files, rather than by hard coding. Understanding dependency Injection
Dependency injection and inversion of control are the same concepts. Specifically, when a role (possibly a Java instance, caller) needs the assistance of another role (another Java instance, called), in the traditional programming process, generally, the caller creates the called instance. However, in spring, the creation of the called instance is no longer completed by the caller, so it is called control inversion. The creation of the called instance is usually completed by the spring container and then injected into the caller, therefore, it is also called dependency injection.
Whether it is dependency injection or control reversal, spring uses a dynamic and flexible way to manage various objects. The specific implementation between objects is transparent to each other. Before understanding dependency injection, let's look at how this problem can be solved in various social forms: a person (Java instance, caller) needs an ax (Java instance, called ).
(1) there is almost no social division of labor in the primitive society. The caller can only sharpen an ax by himself ). The corresponding scenario is: the caller in the Java program creates the caller himself.
(2) entering the industrial society, factories appear. The ax is no longer done by ordinary people, but is produced in the factory. At this time, the ax user (caller) needs to find the factory and buy the ax, so there is no need to care about the production process of the ax. Corresponds to the design pattern of the simple factory of Java program.
(3) In the "pay-as-you-go" society, people who need an ax do not need to find a factory and sit at home to issue a simple command: they need an ax. The ax naturally appeared in front of him. Corresponding to spring dependency injection.
In the first case, when a Java instance caller creates a called Java instance, The called Java class must appear in the caller's code. It is impossible to achieve loose coupling between the two.
In the second case, the caller does not need to care about the specific implementation process of the caller. Instead, the caller needs to find an instance that complies with a certain standard (interface. At this time, the called code is oriented to interface programming, which can decouple the caller from the called one. This is also the reason why the factory mode is widely used. However, the caller needs to locate the factory by himself, and the caller is coupled with a specific factory.
In the third case, the caller does not need to locate the factory by himself. When the program runs to be called, the system automatically provides the called instance. In fact, both the caller and the called are under spring management, and the dependency between the two is provided by spring.
The so-called dependency injection means that, when a program is running, if you need to call another object for assistance, you do not need to create a caller in the code, but rely on external injection. Spring dependency injection has almost no requirements on callers and callers. It fully supports the management of dependencies between pojo. There are two types of dependency injection:
· Set Value injection.
· Construct injection.
Set Value Injection
Set Value injection refers to the instance that is passed into the caller through the setter method. This injection method is simple and intuitive, so it is widely used in spring dependency injection. The following code indicates the person interface.
// Define the person Interface
Public interface person
{
// Define an ax method in the person Interface
Public void useaxe ();
}
Then the axe Interface
// Define the axe Interface
Public interface axe
{
// There is a method for cutting in the axe Interface
Public void chop ();
}
Person implementation class
// Implement the person interface in Chinese
Public class Chinese implements person
{
// Programming for the axe interface, rather than the specific implementation class
Private axe;
// Default constructor
Public Chinese ()
{}
// Setter method required for setting value Injection
Public void setaxe (axe)
{
This. AXE = axe;
}
// Useaxe method for implementing the person Interface
Public void useaxe ()
{
System. Out. println (axe. Chop ());
}
}
Axe's first implementation class
// The first axe implementation class stoneaxe
Public class stoneaxe implements axe
{
// Default constructor
Public stoneaxe ()
{}
// Implement the chop method for the axe Interface
Public String chop ()
{
Return "cutting firewood slowly ";
}
}
The following uses the spring configuration file to organize the person instance and the axe instance together. The configuration file is as follows:
<! -- The following is a standard XML file header -->
<? XML version = "1.0" encoding = "gb2312"?>
<! -- The following line defines the DTD of the spring xml configuration file -->
Http://www.springframework.org/dtd/spring-beans.dtd>
<! -- The above three lines are the same for all spring configuration files -->
<! -- Root element of the spring configuration file -->
<Beans>
<! -Define the first bean. The bean ID is Chinese, and class specifies the implementation class of the bean instance -->
<Bean class = Lee. Chinese ID = Chinese>
<! -- The property element is used to specify the attributes for container injection. The Axe attribute requires container injection. Here value injection is set. Therefore, the Chinese class must have the setaxe method. -->
<Property name = "Axe">
<! -- Inject the reference of another bean to the Chinese Bean -->
<Ref local = "" stoneaxe "/">
</Property>
</Bean>
<! -- Define stoneaxe Bean -->
<Bean class = Lee. stoneaxe id = stoneaxe/>
</Beans>
From the configuration file, you can see the flexibility of spring bean management. The dependencies between bean and bean are organized in the configuration file, rather than written in the code. By specifying the configuration file, spring can precisely inject attributes into each bean. Therefore, the Bean class Element in the configuration file must be a real implementation class instead of an interface.
Spring automatically takes over the property element definition in each bean definition. After Spring executes a constructor without parameters and creates a default bean instance, it calls the corresponding setter method to inject the property value to the program. The property value defined by property will not be automatically created and managed by the bean, but will be passively received by spring injection.
The ID attribute of each bean is the unique identifier of the bean. The program accesses the bean through the ID attribute, and the dependency between the bean and the bean is also completed through the ID attribute.
See the main program section below:
Public class beantest
{
// Main method, program entry
Public static void main (string [] ARGs) throws exception
{
// Because it is an independent application, the context of spring is explicitly instantiated.
Applicationcontext CTX = new filesystemxmlapplicationcontext ("bean. xml ");
// Obtain the bean instance by using the person bean ID, which is interface-oriented. Therefore
// Force type conversion to interface type
Person P = (person) CTX. getbean ("Chinese ");
// Directly execute the useraxe () method of person.
P. useaxe ();
}
}
The execution result of the program is as follows:
Cutting firewood with stone axes is slow
When the main program calls the useaxe () method of person, the axe instance needs to be used in the method body of this method, but there is no place in the program to couple the specific person instance with the axe instance. In other words, the program does not include an axe instance for the person instance, and the axe instance is dynamically injected by spring during running.
The person instance does not need to understand the specific implementation of the axe instance, or even the axe creation process. When the program runs on an axe instance, spring creates an axe instance and injects it to the caller who needs the axe instance. When the person instance runs where an axe instance is required, an axe instance is generated for the person instance.
The caller does not need to care about the implementation process of the called user, but can even omit the factory positioning (actually allocated on Demand !). The following is a simple script for compiling and running the application with ant:
<? XML version = "1.0"?>
<! -- Define the basic information for compiling the project -->
<Project name = "Spring" default = "." basedir = ".">
<! -- Define the library files required to compile and run the project -->
<Path id = classpath>
<! -- Store spring. jar and other third-party class libraries in this path -->
<Fileset dir =... lib>
<Include name = "*. Jar"/>
</Fileset>
<! -- At the same time, you also need to reference the compiled class file -->
<Pathelement Path = "."/>
</Path>
<! -- Compile all java files -->
<Target description = "compile all source code" name = "compile">
<! -- Specify the storage location of the compiled class file -->
<Javac DEBUG = "true" destdir = ".">
Deprecation = "false" optimize = "false" failonerror = "true">
<! -- Specify the storage location of the source file to be compiled -->
<SRC Path = "."/>
<! -- Specify the location of the class library required for compiling these java files -->
<Classpath refID = "classpath"/>
</Javac>
</Target>
<! -- Run a specific main program -->
<Target description = "run the main class" name = "run" depends = "compile">
<! -- Specify the main program to run: Lee. beantest. -->
<Java failonerror = "true" fork = "yes" classname = "Lee. beantest">
<! -- Specify the location of the class library required to run these java files -->
<Classpath refID = "classpath"/>
</Java>
</Target>
</Project>
If you need to rewrite the axe implementation class. Or, provide another implementation class for the person instance. The person interface and Chinese class do not need to be changed. You only need to provide the implementation of another axe, and then make simple modifications to the configuration file.
Another implementation of axe is as follows:
// Another axe implementation class steelaxe
Public class steelaxe implements axe
{
// Default constructor
Public steelaxe ()
{}
// Implement the chop method for the axe Interface
Public String chop ()
{
Return "cutting firewood with an axe is really fast ";
}
}
Then, modify the original spring configuration file and add the following line in it:
<! -- Define a steelaxe Bean -->
<Bean class = Lee. steelaxe id = steelaxe/>
This row redefined an axe implementation: steelaxe. Modify the configuration of the Chinese bean and change the original stoneaxe to steelaxe. That is
<Ref local = "" stoneaxe "/">
Change
<Ref local = "" steelaxe "/">
Execute the program again and you will get the following results:
Cutting firewood with a steel axe is really fast
There is no code coupling between person and axe, and the dependency between bean and bean is managed by spring. The setter method is used to inject attributes into the target bean, which is called set value injection.
The replacement of business objects is quite simple. The dependency between objects is separated from the code and managed dynamically through the configuration file.
Constructor Injection
Constructor injection is used to set the dependency through constructor, rather than the setter method. Make a simple modification to the Chinese class of the previous code. The modified code is as follows:
// Implement the person interface in Chinese
Public class Chinese implements person
{
// Programming for the axe interface, rather than the specific implementation class
Private axe;
// Default constructor
Public Chinese ()
{}
// Construct a constructor with parameters required for the injection.
Public chinse (axe)
{
This. AXE = axe;
}
// Useaxe method for implementing the person Interface
Public void useaxe ()
{
System. Out. println (axe. Chop ());
}
}
In this case, the setaxe method in the Chinese class is not required. When constructing a person instance, spring injects the dependent axe instance into the person instance. A simple modification is also required to construct the injected configuration file. The modified configuration file is as follows:
<! -- The following is a standard XML file header -->
<XML version = "1.0" encoding = "gb2312"?>
<! -- The following line defines the DTD of the spring xml configuration file -->
Http://www.springframework.org/dtd/spring-beans.dtd>
<! -- The above three lines are the same for all spring configuration files -->
<! -- Root element of the spring configuration file -->
<Beans>
<! -Define the first bean. The bean ID is Chinese, and class specifies the implementation class of the bean instance -->
<Bean class = Lee. Chinese ID = Chinese>
<Constructor-Arg> <ref bean = "steelaxe"> </constructor-Arg>
</Bean>
<! -- Define stoneaxe Bean -->
<Bean class = Lee. steelaxe id = steelaxe/>
</Beans>
The execution effect is exactly the same as that when steelaxe is used to set the value for injection. The difference is that the axe attribute in the person instance is created differently-set value injection is to create a default bean instance, and then call the corresponding constructor to inject dependencies. The constructor injection completes the dependency injection when the bean instance is created.