Spring: Automatic Assembly
Bean's automated assembly
- Automatic spring assembly using a method satisfying dependent bean
- spring will look for their dependent bean is a bean in the application context.
Spring assembly mechanism in three bean, namely:
- Explicit arranged in xml;
- Explicit arranged in java;
- Implicit bean discovery mechanism and automatic assembly.
Here we talk about the third: automated assembly bean.
Spring needs to achieve automatic assembly from two angles, or that two operations:
- Scanning component (component scanning): spring bean automatically find application context created;
- Automatic assembly (autowiring): spring automatically satisfy the dependencies between the bean, that is, we say the IOC / DI;
Scanning and automatic assembly configuration component composition play great power, so that the display is reduced to a minimum.
It recommended not to use automated assembly xml configuration, and use notes.
Environment to build
A person has two pets
public class Dog {
public void shout() {
System.out.println("wang~");
}
}
public class Cat {
public void shout() {
System.out.println("miao~");
}
}
public class Person {
private Cat cat;
private Dog dog;
public void setCat(Cat cat) {
this.cat = cat;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
}
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.cong.pojo.Dog"/>
<bean id="cat" class="com.cong.pojo.Cat"/>
<bean id="person" class="com.cong.pojo.Person">
<property name="name" value="cong"/>
<property name="dog" ref="dog"/>
</bean>
</beans>
test
public class TestAuto {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person");
person.getCat().shout();
person.getDog().shout();
}
}
ok, no problem
byName
autowire byName (automatic assembly by name)
Xml since manual configuration process, and capitalization letters and gaps often occurs an error, and can not be checked, so as to reduce the efficiency of development.
Automatic assembling will avoid these errors, and easy to configure.
<bean id="person2" class="com.cong.pojo.Person" autowire="byName"/>
test
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person2");
person.getCat().shout();
person.getDog().shout();
}
Test no problem!
Do a little modification
The cat's bean id change it
<bean id="cat1" class="com.cong.pojo.Cat"/>
Again test errorjava.lang.NullPointerException
Because according to the rules byName not find a corresponding set method, there is no real setCat execution, the object is not initialized, it will report a null pointer error when calling.
summary:
When a node with a bean property of autowire byName.
- The method finds all the set of its class name, for example setCat, obtaining the first set and remove the lowercase character string, i.e., cat.
- Go look for spring container if there is this string name of the object id.
- If so, remove the injection; if not, a null pointer exception reported.
byType
autowire byType (autowiring by type)
Use autowire byType first need to ensure that: objects of the same type, the only vessel in the spring.
If not unique, it is not the only exception will be reported NoUniqueBeanDefinitionException
.
<bean id="person3" class="com.cong.pojo.Person" autowire="byType"/>
Test, no problem
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person3");
person.getCat().shout();
person.getDog().shout();
}
At this time, we registered a cat2
<bean id="cat" class="com.cong.pojo.Cat"/>
<bean id="cat2" class="com.cong.pojo.Cat"/>
Run, you will get an error
NoUniqueBeanDefinitionException
Commented cat
<!--<bean id="cat" class="com.cong.pojo.Cat"/>-->
<bean id="cat2" class="com.cong.pojo.Cat"/>
Test, you can, because it is assembled by type, so it does not announce an exception, it does not affect the final result. Even the id attribute removed, does not affect the results.
Use annotations
jdk1.5 began to support annotations, spring2.5 began full support annotations.
Use annotations need to introduce context header in the configuration file, write directly on the idea of <context:context:annotation-config
a carriage return is automatically imported.
And open support for annotations<context:annotation-config/>
@Autowired
- @Autowired is by type of automatic assembly, id does not match the support.
- You need to import the spring-aop package!
- If a plurality of the same type of bean, automatically assembling the class name lowercase bean,
A new class Pserson removed setter
public class Person2 {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
}
Re-create a configuration file, beans.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="dog" class="com.cong.pojo.Dog"/>
<bean id="cat" class="com.cong.pojo.Cat"/>
<bean id="person2" class="com.cong.pojo.Person2"/>
</beans>
Test, no problem
@Test
public void test4(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person2 person2 = (Person2) context.getBean("person2");
person2.getCat().shout();
person2.getDog().shout();
}
@Autowired extension
@Autowired can set properties required
Description:
false, the object can be null;
true, the object must exist objects can not be null.
//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;
@Qualifier
- @Autowired according to the type of automatic assembly, the assembly may be automatically coupled @Qualifier manner according byName
- @Qualifier not be used alone.
Beans.xml modify the contents of the configuration file, and add dog2 cat2
<context:annotation-config/>
<bean id="dog" class="com.cong.pojo.Dog"/>
<bean id="dog2" class="com.cong.pojo.Dog"/>
<bean id="cat" class="com.cong.pojo.Cat"/>
<bean id="cat2" class="com.cong.pojo.Cat"/>
<bean id="person2" class="com.cong.pojo.Person2"/>
Run, can, @ autowired assembly will automatically default type lowercase bean
Modified again, ensure the existence of the object type. And the name is not the default name of the class!
<context:annotation-config/>
<bean id="dog1" class="com.cong.pojo.Dog"/>
<bean id="dog2" class="com.cong.pojo.Dog"/>
<bean id="cat1" class="com.cong.pojo.Cat"/>
<bean id="cat2" class="com.cong.pojo.Cat"/>
<bean id="person2" class="com.cong.pojo.Person2"/>
If this time is no longer Person2 write @qualifier, will error
Add Qualifier annotation on the property
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
In this way, the test would be no problem
@Resource
- @Resource if specified attribute name, attribute byName the press fitting manner lookup;
- Secondly, then the default byName assembled manner;
- If the above are not successful, press byType way automatic assembly.
- Not successful, reported abnormal.
Entity class
public class Person3 {
//如果允许对象为null,设置required = false,默认为true
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
}
Then create a new profile beans2.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="dog" class="com.cong.pojo.Dog"/>
<bean id="cat1" class="com.cong.pojo.Cat"/>
<bean id="cat2" class="com.cong.pojo.Cat"/>
<bean id="person3" class="com.cong.pojo.Person3"/>
</beans>
Test, no problem
//@resource
@Test
public void test5(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans2.xml");
Person3 person3 = (Person3) context.getBean("person3");
person3.getCat().shout();
person3.getDog().shout();
}
At this time, delete cat2
<bean id="dog" class="com.cong.pojo.Dog"/>
<bean id="cat1" class="com.cong.pojo.Cat"/>
<!--<bean id="cat2" class="com.cong.pojo.Cat"/>-->
<bean id="person3" class="com.cong.pojo.Person3"/>
</beans>
Leaving only entity class notes
@Resource//(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
Test, or no problem
Conclusion: The first were byName lookup failure; then byType find, success.
summary
@Autowired and @Resource similarities and differences:
- @Autowired assembly can be used with @Resource bean. Can be written in the field, or write on the setter methods.
- Default fitting @Autowired by type (belonging to the spring specifications), by default in claim dependent objects must be present, if you want to allow null values, can set its required property is false, such as: @Autowired (required = false), if we want assembly may be combined with the name used for annotations @Qualifier
- @Resource (forever, the J2EE), assembled in accordance with a default name, which can be specified by the name attribute. If you do not specify a name attribute, when the notes written on the field, take the default field name lookup by name, if the notes written on the attribute setter methods to take default name for assembly. When that matches the name can not be found when assembled in accordance with the type of bean. However, note that if the name attribute if specified, will only be assembled by name.
Their role is injected into the same object with the annotation mode, but a different order of execution. @Autowired first byType, @ Resource to byName.