Automatic assembly of spring 04 bean

Posted by pit on Sat, 22 Jan 2022 21:24:06 +0100

  • Automatic assembly is a way for Spring to meet bean dependencies. Before that, you must manually inject dependencies into beans, otherwise the attribute will be empty
  • Automatic assembly: Spring will automatically find the context and automatically assemble properties for the bean

There are three ways to assemble in Spring

  1. Display configuration in xml

  2. Display configuration in java

  3. Implicit automatic assembly bean [important]

  4. Environment construction: create Person class, Cat class and Dog class. The relationship between the classes is that one Person has two pet cats and dogs (for convenience, you don't create packages, but directly create classes under main/java), and one Person has two pets

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Person {
    private String name;
    private Cat cat;
    private Dog dog;
}

public class Cat {
    public void shout(){
        System.out.println("cat ");
    }
}
public class Dog {
    public void shout(){
        System.out.println("Woof, woof");
    }
}

Then create beans XML configuration file, create a Person object as before, and use the P tag

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="cat" class="com.baifu.pojo.Cat"/>
    <bean id="dog" class="com.baifu.pojo.Dog"/>
    <bean id="person" class="com.baifu.pojo.Person" p:name="Baifu" p:cat-ref="cat" p:dog-ref="dog"/>



</beans>

After that, write a test method and let the pet bark

public class MyTest {
    @Test
    public void Test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Person person = context.getBean("person", Person.class);
        person.getCat().shout();
        person.getDog().shout();
    }
}
// results of enforcement
/*
    cat 
    Woof, woof
*/

This is what manual assembly did before. Let's use automatic assembly.

XML auto assembly

To use auto assembly, configure the autowire attribute in the bean tag. The autowire attribute has byName, byType, constructor, default and no attributes

byName

Using byName automatic assembly, Spring will automatically find the missing dependencies of the Person class in the container through the field after the set method (such as setCat. If the field is Cat, go to find the Cat object). If the missing classes are Cat and dog, go to find the above Cat and dog.

cat and dog classes still need to be injected into xml files, but they don't need to be assembled in person

	<bean id="cat" class="com.baifu.pojo.Cat"/>
    <bean id="dog" class="com.baifu.pojo.Dog"/>
    <bean id="person" class="com.baifu.pojo.Person" p:name="Baifu" autowire="byName"/>

Run the above test method and the results are the same.

Note: byName auto assembly requires the id of the bean. For example, if the Cat of the above id becomes cat1, Spring cannot find this object; And pay attention to case. For example, if Cat is written as Cat, Spring will not find it. If the auto assembly cannot find the required object, the dependency will become null.

byType

Using byType automatic assembly, Spring will automatically find the bean corresponding to the type required by the dependency in the container. For example, if the dependency required by person is Cat type and Dog type, it will find these two types of objects. Because it is only related to type, the corresponding bean can even have no id

<bean  class="com.baifu.pojo.Cat"/>
<bean  class="com.baifu.pojo.Dog"/>
<bean id="person" class="com.baifu.pojo.Person" p:name="Baifu" autowire="byType"/>

Note: since the target is found by type, the problem is obvious, that is, there can be no more than one bean of the same type! If there cannot be cat and cat1 at the same time, otherwise the IDEA will directly prompt that there is a problem with this bean, and the required dependency types must be globally unique.

Auto assemble using annotations

The introduction of annotation-based configuration raised the question of whether this approach is "better" than XML.

To use annotations, you need to configure annotation support and import context constraints in the header of the configuration file

<?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/>

</beans>

@Autowired

Automatic assembly can be realized by adding use on attribute or use on set

Using @ Autowired, you can inject dependencies without writing a set method!

public class People {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}

After @ Autowired is used, during assembly

First, find the type corresponding to the attribute according to byType. If there is only one object of this type, assemble it directly
If there are multiple objects of this type, find the object named class name according to byName (such as cat object corresponding to cat type) for assembly
If both methods fail, the assembly fails and the property is null

<!--Automatic assembly using annotations-->
<!--about cat,Using byName-->
<bean id="cat" class="Cat"/>
<bean id="cat2" class="Cat"/>
<!--about dog,Using byType-->
<bean id="dog" class="Dog"/>
<bean id="person" class="Person" p:name="baifu"/>

Expand it. Click the @ Autowired interface to see that there is a required attribute, which is true by default

public @interface Autowired {
    boolean required() default true;
}

The required attribute is set to ture by default to limit that the attribute with @ Autowired annotation cannot be empty, that is, an error will be reported when the object to be assembled is not found; If it is set to false, the object to be assembled cannot be found, and the program will not report an error

If it is set to false on the dog attribute, delete beans XML configured dog object

public class Person {
    private String name;
    @Autowired
    private Cat cat;
    @Autowired(required = false)
    private Dog dog;
}
   <!--Auto assemble using annotations-->
    <!--about cat,Using byName-->
    <bean id="cat"  class="com.baifu.pojo.Cat"/>
    <bean id="cat123"  class="com.baifu.pojo.Cat"/>
    <!--about dog,Using byType-->
<!--    <bean id="dog"  class="com.baifu.pojo.Dog"/>-->
    <bean id="person" class="com.baifu.pojo.Person" p:name="Baifu"/>
    <context:annotation-config/>

Execute the test method and the result is

// results of enforcement

// cat 
// java.lang.NullPointerException
// ...

The null pointer exception here is due to the call to getDog() For the shot () method, since it is allowed to be empty, but there is no matching object, the getdog () obtained here is empty.

If required = false is not set, delete beans For the dog object configured with XML, an error will be reported when executing the test method

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
 No qualifying bean of type 'com.baifu.pojo.Dog' available: 
 expected at least 1 bean which qualifies as autowire candidate.Dependency annotations: 
 {@org.springframework.beans.factory.annotation.Autowired(required=true)}

That is, due to the error that required = true, but the object cannot be found for assembly (expected at least 1 bean).

@Qualifier

If @ Autowired uses a complex environment, it can be used with @ Qualifier@ There is only one attribute value in Qualifier. After setting, the automatic assembly will directly find the object with the corresponding id. if the IDEA cannot be found, it will be marked in red.

Note: after configuring @ Qualifier, @ Autowired will only find the specified object, and will shield the automatic assembly of byType and byName.

In beans Add two cats and two dogs to the XML to avoid byType assembly, and bring 1 and 2 after id to avoid byName assembly

<!-- @Qualifier Find object-->
<bean id="cat1" class="Cat"/>
<bean id="cat2" class="Cat"/>
<bean id="dog1" class="Dog"/>
<bean id="dog2" class="Dog"/>
<bean id="person" class="Person" p:name="baifu"/>

Specify a specific object through @ Qualifier annotation (specified by id in xml file)

public class Person {
    private String name;
    @Autowired
    @Qualifier(value = "cat2")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog2")
    private Dog dog;
}

Run discovery found.

@Resource

@The Resource annotation is the annotation provided by JAVA, which is functionally a combination of @ Autowired and @ Qualifier.

That is, @ Resource can also be automatically assembled according to byType and byName, which is the same as @ Autowired; At the same time, @ Resource also has a name attribute, which can specify the object to be assembled, which is the same as @ Qualifier

public class Person {
    private String name;
    @Resource(name = "cat1")
    private Cat cat;
    @Resource(name = "dog1")
    private Dog dog;
}

Test OK

  • @autowire is implemented by byType first, and this object must exist

  • @resource is implemented by byName by default. If it cannot be found, it is implemented by byType

summary

This section learned how to assemble bean s automatically

  • Using xml, set the attribute of autowired to byType or byName in the bean tag
  • Generally speaking, @ Autowired is enough to use annotations. If you can't, combine @ Qualifier or powerful @ Resource

reference resources: https://blog.csdn.net/qq_43560701/article/details/119880416

Topics: Java Spring jar