IoC -- Inversion of Control, Control Inversion
In Java Development, IoC means that the classes you have designed are handed over to the system for control, rather than being controlled within your class. IoC is a component design method that prevents service consumers from directly relying on service providers. It is a design principle that reduces the dependency between classes.
DI -- Dependency Injection (Dependency Injection)
That is, the dependency between components is determined by the container at runtime. In the image, the container dynamically injects a dependency into the component.
The goal of dependency injection is not to bring more functions to the software system, but to improve the probability of Component Reuse and build a flexible and scalable platform for the system. Through the dependency injection mechanism, we only need simple configuration, and can specify the resources required by the target without any code to complete its own business logic, you don't have to worry about where and who the specific resources come from.
1: Control reversal:
Who controls who? What is the control? Why is reverse (corresponding to positive )? What has reversed? Why does it need to be reversed?
2: Dependency:
What is dependency (understood by nouns and by verbs )? Who depends on who? Why is dependency required? Depends on what?
3: injection:
Who injected it? What is injected? Why injection?
4: Is dependency injection the same concept as control reversal?
5: What are participants?
6: What is IoC/DI? What can we do? How? Where is it used?
I still cannot fully answer and understand it. It doesn't matter. Let's take a look at the evolution of the basic idea of IoC/DI, and then answer these questions later.
IoC container
A simple understanding is: the software that implements the IoC idea and provides object creation, object assembly, and object lifecycle management is the IoC container.
IoC understanding
1: The application does not need to take the initiative to create a new object, but describes how the object should be created.
IoC containers help you create them, that is, passive instantiation;
2: applications do not need to actively assemble dependencies between objects, but describe which service is needed
The IoC container will help you assemble (that is, associate them together) and passively accept assembly;
3: active and passive, reflecting Hollywood rules: Don't call us, we will call you
4: embody the Demeter rule (minimum knowledge principle): The application does not know the specific implementation of dependencies, but only knows the objects that need to provide certain services (interface-Oriented Programming). It is loosely coupled, an object should have as little understanding as possible about other objects and should not talk to strangers (implementations ).
5: it is a component design method that prevents service consumers from directly relying on service providers. It is a design principle that reduces dependencies between classes.
How IoC/DI Container development needs to be changed
1: The application does not actively create objects, but describes how to create them.
2: services are not directly assembled in the application code, but the container is responsible for assembling the components to describe which service is required.
That is to say, all components are passive, and the initialization and assembly of components are the responsibility of the container. The application only needs to implement the functions of the application after obtaining the corresponding components.
One note
IoC/DI is an idea, not a pure implementation technology. IoC is a common framework. It only involves the transfer of control to the Framework. Therefore, it cannot be called an IoC container because IoC is implemented, the IoC container is also called the DI function, because the container is responsible for creating and assembling the component relationship, and also needs to manage the component lifecycle.
N tool preparation
1: Eclipse + Jdk6.0. The example uses Eclipse Java ee ide for Web Developers, Version: Helios Service Release 1.
2: spring-framework-3.1.0.M2-with-docs.zip
Build Environment
1: Create a project in Eclipse. Set it to Spring3test.
2: add the jar packages under dist in the release package to Eclipse.
3: Obtain the dependent packages required by Spring based on the Spring Project. When the network is connected, run projects/build-spring-framework/build through Ant. the downloaded jar package is automatically downloaded under projects/ivy-cache/repository.
4: add these jar packages to Eclipse for convenience.
DEVELOPMENT INTERFACE
Java code:
[Java]
Public interface HelloApi {
Public String helloSpring3 (int );
}
Development Implementation class
Java code:
[Java]
Public class HelloImpl implements HelloApi {
Public String helloSpring3 (int ){
System. out. println ("hello Spring3 =" + );
Return "OK, a =" +;
}
}
Configuration File
1: create a file named applicationContext. xml under src.
2: search for an example in the Spring release package, such as projects \ org. springframework. applicationContext under context \ src \ test \ java \ org \ springframework \ jmx. xml: delete all the configurations, and leave the basic xml definition and root element. It is a DTD version and is still in version 2.0.
Java code:
[Java]
3: Spring3 Schema version is recommended, for example:
<? Xml version = "1.0" encoding = "UTF-8"?>
<Beans xmlns = "http://www.springframework.org/schema/beans"
Xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance"
Xmlns: context = "http://www.springframework.org/schema/context"
Xmlns: aop = "http://www.springframework.org/schema/aop"
Xmlns: tx = "http://www.springframework.org/schema/tx"
Xsi: schemaLocation ="
Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
Http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
Http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
Http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
">
...........................
</Beans>
4: Configure applicationContext. xml as follows:
Java code:
[Java]
<Bean name = "helloBean" class = "cn. S. Spring3.hello. HelloImpl"> </bean>
Write the client as follows:
Java code:
[Java]
Package cn. ipvs. Spring3.hello;
Import org. springframework. context. ApplicationContext;
Import org. springframework. context. support. ClassPathXmlApplicationContext;
Public class Client {
Public static void main (String [] args ){
ApplicationContext context = new ClassPathXmlApplicationContext (
New String [] {"applicationContext. xml "});
HelloApi api = (HelloApi) context. getBean ("helloBean ");
String s = api. helloSpring3 (3 );
System. out. println ("the s =" + s );
}
}
Review and conclusion
1: No components of Spring appear in all the Code except the test code.
2: The Customer Code (here our test code) is only for interface programming, without the need to know the specific name of the implementation class. At the same time, we can easily change the configuration file to switch the specific underlying implementation class.
Conclusion
1: first, our components do not need to implement the interface specified by the Framework, so we can easily remove the components from Spring, no modification is required (this is hard to imagine in applications implemented based on the EJB architecture ).
2: The dependency between components is reduced, greatly improving code reusability and maintainability.
3: interface-Oriented Programming
What is Bean in Spring?
In Spring, the subjects that constitute the application and the objects managed by the Spring IoC container are called beans. Simply put, bean is the object initialized, assembled, and managed by the Spring container. In addition, bean has nothing special (there is no difference with other objects in the application ). Bean definitions and dependencies between beans are described by configuring metadata.
Why is Bean used?
The motivation for using the 'bean' name rather than the 'component (component) or 'object' (object) is derived from the Spring framework itself (in part, it is relative to the complicated EJB ).
Spring IoC container
Org. springframework. beans. factory. BeanFactory is the actual representative of the Spring IoC container. The IoC container is responsible for accommodating beans and managing beans.
The Spring IoC container reads the configuration metadata and instantiates, configures, and assembles each object in the application. In general, we use simple and intuitive XML as the description format for configuring metadata. In XML configuration metadata, we can define beans that we want to manage through Spring IoC containers.
IoC/DI is one of the core functions of Spring. The Spring framework provides a set of functions based on IoC.
BeanFactory and ApplicationContext
The org. springframework. beans and org. springframework. context packages are the basis of Spring IoC containers. The Advanced Configuration mechanism provided by BeanFactory makes it possible to manage objects of any nature. ApplicationContext is an extension of BeanFactory and its functions are further enhanced, such as easier integration with Spring AOP and message resource processing (International processing) event transmission and context implementation of different application layers (for example, WebApplicationContext for web applications ).
Interface Selection
In practical applications, users sometimes do not know whether to choose the BeanFactory interface or ApplicationContext interface. However, it is usually better to use ApplicationContext when building a JavaEE application because it not only provides all the features of BeanFactory, at the same time, more declarations can be used to obtain the desired functions.
In short, BeanFactory provides the preparation framework and basic functions, while ApplicationContext adds more features that support enterprise core content. ApplicationContext is fully extended by BeanFactory, so the capabilities and behaviors of BeanFactory are also applicable to ApplicationContext.
The instantiation of Spring IoC containers is very simple, as shown in the following example:
1: first:
Java code:
[Java]
Resource resource = new FileSystemResource ("beans. xml ");
BeanFactory factory = new XmlBeanFactory (resource );
2: Type 2:
Java code:
[Java]
ClassPathResource resource = new ClassPathResource ("beans. xml ");
BeanFactory factory = new XmlBeanFactory (resource );
3: Third:
Java code:
[Java]
ApplicationContext context = new ClassPathXmlApplicationContext (
New String [] {"applicationContext. xml", "applicationContext-part2.xml "});
// Of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) context;
Read multiple configuration files
Method 1:
To load multiple XML files to generate an ApplicationContext instance, you can use the file path as a string array to send it to the ApplicationContext constructor. Bean factory reads bean definitions from multiple files by calling bean defintion reader. Usually, the Spring team tends to do this, because the configuration does not find their combination with other configuration files.
Method 2:
Use one or more <import/> elements to load bean definitions from one or more files. All <import/> elements must be placed before the <bean/> element to complete bean-defined import. Let's take an example:
Java code:
[Java]
<Beans> <import resource = "services. xml"/>
<Import resource = "/resources/messageSource. xml"/>
<Import resource = "/resources/themeSource. xml"/>
<Bean id = "bean1" class = "..."/>
<Bean id = "bean2" class = "..."/>
</Beans>
Common configuration content in the configuration file
In the IoC container, the bean definition is represented by the BeanDefinition object, which contains the following information:
1: fully qualified class name: this is usually the actual implementation class of the defined bean. If you call the static factory method to instantiate the bean, instead of using the conventional constructor, the class name is actually the Class Name of the factory class.
2: bean behavior definition, that is, the creation mode (prototype or singleton), automatic assembly mode, dependency check mode, initialization and destruction method. These definitions determine the bean behavior in the container.
3: The constructor parameters and attribute values used to create bean instances. For example, if bean is used to define the connection pool, you can specify the number of connections and the size limit of the connection pool through attributes or construction parameters.
4: Relationship between beans, that is, collaboration (or dependency ).
Bean name
Each bean has one or more IDs (or identifiers or names, which can be understood as one thing in terms of). These IDS must be unique in the current IoC container.
Of course, you can also define a name for each bean, but it is not necessary. If it is not specified, the container will generate a unique name for it. We will introduce the reason for not specifying the name attribute later (for example, internal bean is not required ).
Bean naming conventions
Bean naming adopts the standard Java Naming Convention, that is, the naming method for the interval between the first letter and the start letter. Such as accountManager and accountService.
Using a unified naming convention for beans will make the configuration easier to understand. In addition, Spring AOP is used. This simple naming method will benefit you a lot.
Bean alias
To provide multiple names for a Bean, you can specify them using the alias attribute, for example:
<Alias name = "fromName" alias = "toName"/>
How to instantiate Bean in a container
When XML description is used to configure metadata, the class attribute of the <bean/> element is used to specify the type of the instantiated object. The class attribute has two main purposes: In most cases, the container will create beans directly by calling the constructor of the specified class through reflection (this is somewhat like using the new operator in Java code); in rare cases, the container will call the static factory method of the class to create the bean instance, the class attribute is used to specify the class that actually has a static factory method (it does not matter whether the object type created by calling the static factory method is the current class or other classes ).
The constructor is used to instantiate the Bean. The previous instance is
Instantiate using static factory Method
When using the static factory method to create a bean, in addition to specifying the class attribute, you also need to use the factory-method attribute to specify the factory method for creating the bean instance. The example is as follows:
<Bean id = "exampleBean"
Class = "examples. ExampleBean2"
Factory-method = "createInstance"/>
Instantiate using the instance factory Method
With this mechanism, the class attribute must be null, and the factory-bean attribute must be specified as the name of the bean containing the factory method in the current (or its ancestor) container, the factory method of the factory bean must be set through the factory-method attribute, and the method cannot be static. The example is as follows:
<Bean id = "exampleBean" factory-bean = "myFactoryBean" factory-method = "createInstance"/>
Use container
BeanFactory is only an advanced factory interface that maintains bean definitions and dependencies. You can use the getBean (String) method to obtain the bean instance. The method provided by BeanFactory is extremely simple. Basic principles behind n dependency injection (DI)
Is the dependency between objects (other objects that work together) only through the following methods: constructor parameters, factory method parameters, you can also set properties for objects created by constructors or factory methods.
Therefore, the container's job is to inject those dependencies when creating beans. Compared to the three independent dependency injection control methods that are controlled by bean itself, such as instantiation, specifying dependencies directly in the constructor, or similar to Service Locator mode, the control is fundamentally reversed, which is the origin of the IoC name.
Benefits of application dependency injection (DI,
After the DI principle is applied, the code is clearer. In addition, when the bean does not worry about the dependency between objects (and when and where to specify the actual class of the dependency), it is easy to implement higher-level loose coupling.
Basic Implementation of dependency injection (DI)
DI has two main injection methods: Setter injection and constructor injection.
You can call the setter method of the bean by calling the keyless constructor or the keyless static factory method to instantiate the bean. Example:
Example -- Java class
Java code:
[Java]
Public class HelloImpl implements HelloApi {
Private String name = "";
Public void setName (String name ){
This. name = name;
}
Public String helloSpring3 (int ){
System. out. println ("hello Spring3 =" + a + ", name =" + name );
Return "OK, a =" +;
}
}
Example -- configuration file
<Bean name = "helloBean" class = "cn. S. Spring3.hello. HelloImpl">
<Property name = "name"> <value> S Spring3 </value> </property>
</Bean>
Example -- Java class
Java code:
[Java]
Public class HelloImpl implements HelloApi {
Private String name = "";
Public HelloImpl (String name ){
This. name = name;
}
Public String helloSpring3 (int ){
System. out. println ("hello Spring3 =" + a + ", name =" + name );
Return "OK, a =" +;
}
}
Example -- configuration file
Java code:
[Java]
<Bean name = "helloBean" class = "cn. S. Spring3.hello. HelloImpl">
<Constructor-arg> <value> javass Spring3 </value> </constructor-arg>
</Bean>
Default Resolution Method
The constructor parameters are matched based on the type. If the type of the constructor parameter in bean definition is clear, the parameter order in bean definition is the order corresponding to the constructor parameter.
Constructor parameter type match
You can use the type attribute to explicitly specify the simple type corresponding to a parameter. For example:
Java code:
[Java]
<Bean id = "exampleBean" class = "examples. ExampleBean">
<Constructor-arg type = "int" value = "7500000" type = "codeph" text = "codeph"/>
<Constructor-arg type = "java. lang. String" value = "42"/>
</Bean>
Index of the constructor Parameter
You can use the index attribute to explicitly specify the sequence in which the constructor parameters appear. For example:
Java code:
[Java]
<Bean id = "exampleBean" class = "examples. ExampleBean">
<Constructor-arg index = "0" value = "7500000"/>
<Constructor-arg index = "1" value = "42"/>
</Bean>
Name of the constructor Parameter
In Spring3, you can use the name of the constructor parameter to directly assign values. For example:
Java code:
[Java]
<Bean id = "exampleBean" class = "examples. ExampleBean">
<Constructor-arg name = "years" value = "7500000"/>
<Constructor-arg name = "ultimateanswer" value = "42"/>
</Bean>
Direct quantity (basic type, Strings type, etc)
<Value/> the element uses a string to specify the value of an attribute or constructor parameter. The JavaBean Attribute Editor converts a String from the java. lang. String type to the actual attribute or parameter type. Example:
Java code:
[Java]
<Bean id = "myDataSource" class = "org. apache. commons. dbcp. BasicDataSource">
<Property name = "driverClassName">
<Value> oracle. jdbc. driver. OracleDriver </value>
</Property>
<Property name = "url">
<Value> jdbc: oracle: thin: @ localhost: 1521: orcl </value>
</Property>
<Property name = "username"> <value> test </value> </property>
<Property name = "password" value = "test"/>
</Bean>
Value can be used as a child element or attribute.
Nidref Element
The idref element is used to pass the IDs of other beans in the container to the <constructor-arg/> or <property/> element, and provides the error verification function. The idref element is similar to the <value> element. It only transmits a string to facilitate xml check. Example:
Java code:
[Java]
<Bean id = "theTargetBean" class = "..."/>
<Bean id = "theClientBean" class = "...">
<Property name = "targetName"> <idref bean = "theTargetBean"/> </property>
</Bean>
The above bean definition snippets are completely equivalent to the following fragments (at runtime)
<Bean id = "theTargetBean" class = "..."/>
<Bean id = "client" class = "...">
<Property name = "targetName"> <value> theTargetBean </value> </property>
</Bean>
Continued idref Element
The main reason why the first form is more desirable than the second is that the idref flag allows the container to verify whether the referenced bean exists during deployment. In the second method, the targetName attribute value passed to the client bean is not verified. Any input error is only found when the client bean is actually instantiated (possibly accompanied by a fatal error ). If the client bean is a prototype bean, this input error (and the resulting exception) may be detected long after the container is deployed.
If the referenced bean is in the same XML file and the bean name is bean id, you can use the local attribute, this attribute allows the XML parser to verify the referenced bean when parsing the XML file, for example:
<Property name = "targetName">
<Idref local = "theTargetBean"/>
</Property>
Reference other bean (collaborators)-ref Element
Although it is a reference to another object, there are three different forms of pointing to another object through id/name. Different Forms will determine how to handle the scope and verification.
1: The first and most common form is to use <ref/> to mark the specified target bean. Example:
<Ref bean = "someBean"/>
2: The second form is to use the local attribute of ref to specify the target bean. It can use the XML parser to verify whether the referenced bean exists in the same file. Example:
<Ref local = "someBean"/>
3: The third method is to reference the bean in the parent container of the current container by using the parent attribute of ref, which is not commonly used. Example:
Java code:
[Java]
<Bean id = "accountService" class = "com. foo. SimpleAccountService"> </bean>
<Bean id = "accountService" <-- note that the name is the same as that of parent --> class = "org. springframework. aop. framework. ProxyFactoryBean">
<Property name = "target"> <ref parent = "accountService"/> </property>
</Bean>
Internal Bean
The so-called inner bean refers to the bean defined by the <bean/> element in the <property/> or <constructor-arg/> element of a bean. The internal bean definition does not require the id or name attribute. Even if the id or name attribute value is specified, it will be ignored by the container. Example:
Java code:
[Java] www.2cto.com
<Bean id = "outer" class = "...">
<Property name = "target">
<Bean class = "com. mycompany. Person">
<Property name = "name" value = "Fiona Apple"/>
<Property name = "age" value = "25"/>
</Bean>
</Property>
</Bean>
Author: jinnianshilongnian