Summary of Three Ways of Assembling spring with bean

  • 2021-07-03 00:14:36
  • OfStack

Preface

During this period of learning Spring, dependency injection DI and aspect-oriented programming AOP are the core parts of Spring framework. This time, I mainly summarize the assembly mode of bean with dependency injection.

What is dependency injection? It can also be called inversion of control. Simply put, to complete slightly complex business logic, multiple classes may be needed, and some classes will refer to instances of other classes, which can also be called dependence on other classes. The traditional method is to directly reference that class object as one of its own attributes, but if we create the object of this class every time, we will create the object of the dependent class, and if that class may not be used in the future, we need to delete this object in this class, which destroys the reusability of the code and leads to high coupling!

The emergence of dependency injection can solve this problem well. Dependency injection is that the system is responsible for coordinating the creation of dependency objects of classes. We don't need to show the creation of dependency objects by ourselves, but the system injects this object into us, and the system controls the creation of this object, which is also called inversion of control.

Spring injects objects into us in three ways:

Implicit bean scan discovery mechanism and automatic assembly Display configuration in java Display configuration in XML

Type 1:

spring realizes automatic assembly from two angles: component scanning and automatic assembly.

When a class is annotated with @ Component, it means that the class will act as a component class, and spring will create bean for this class. When the bean is referenced in the application, the spring automatically scans the pre-specified packets for the bean. However, spring does not enable component scanning by default, and can be configured in XML <context:component-scan base-package="xx"/> . There is another method: create a new configuration class, and you don't need to write anything in the class. Add @ ComponentScan annotation to the configuration class, and spring will automatically scan the package where the configuration class is located. Generally, xml configuration should be preferred. The following is a small example of the function of bbs forum system users posting:


package bbs.dao;
@Component
public interface Postdao {
 /*
 * User posting   , post Table to add post information 
 */
 public int addpost(@Param("title") String title,@Param("content") String content,@Param("userid") int userid);
}

package bbs.dao;
@Component
public interface Userdao {
 /*
 *  After the user posts, user Table adds the number of posts posted by users 1
 */
 public int addpost(int userid);
}

Then create an postservice interface and its implementation class in the bbs. service package, which depends on Postdao and Userdao.


package bbs.service;
public interface PostService {
 /*
  After the user posts, the post information is added first and then the number of posts is updated 
 */
 public void addpost(String title,String content,int userid);
}

package bbs.service;
@Component
public class PostserviceImpl implements PostService {

 private Postdao postdao;
 private Userdao userdao;

// @Autowired
// public void setPostdao(Postdao postdao)
// {
// this.postdao=postdao;
// }
//
// @Autowired
// public void setUserdao(Userdao userdao)
// {
// this.userdao=userdao;
// }

 @Autowired
 public PostserviceImpl(Postdao postdao,Userdao userdao)
 {
 this.userdao=userdao;
 this.postdao=postdao;
 }

 public void addpost(String title, String content, int userid) {
 int i=postdao.addpost(title, content, userid);
 int j=userdao.addpost(userid);
 if(i==1&j==1)
  System.out.println(" Post Successfully ");
 else
  System.out.println(" Posting failed ");
 }
}

@ Component can annotate the interface implementation, but it is found that userdao and postdao interfaces are also added, which can be removed, because I use mybatis to configure the database operation in xml and dynamically implement dao interface. It will be mentioned later. The @ Autowired annotation in the above code implements bean auto-assembly and looks for the required bean in the component class in the spring application context. There are generally two assembly methods: constructor and Setter method (other method names will do, as long as the injected bean can be made an attribute of this class.)

It is also possible that spring does not find a matching bean and throws an exception, adding @ Autowired required=false If there is no matching bean, spring will leave the bean in an unassembled state, and the assembly will not be successful. It is also possible that there are many bean with the same name, which will cause ambiguity. 1. Add annotations to component classes @Qualifier() Write the id of this bean in parentheses, and also add it when injecting @Qualifier() , write id with bean. Like this:


@Component
@Qualifier("postdao")
public interface Postdao{
. . . . 
}
 
@Component
@Qualifier("userdao")
public interface Userdao{
. . . . 
}

@Autowired
@Qualifier("usedao")
public void setUserdao(Userdao userdao)
{. . . 
}
 
@Autowired
@Qualifier("postdao")
public void setUserdao(Postdao postdao)
{. . . 
}

Because java does not allow multiple annotations of the same type to appear repeatedly on the same entry, all injections adopt set mode. But you can actually create custom qualifier annotations. I won't introduce it here.

Type 2:

Assemble bean with java code

It is more convenient to use component scanning and automatic assembly, but if we want to use the class of the third-party library because of the demand, there is no way to annotate the class in the third-party library in this case, so we can't use the first method. In this case, display assembly can be used, and java code or xml display assembly bean can be used. Using java code, first create a new configuration class JavaConfig, which is bean required for configuration. There should be no business logic code, so build a separate class.


@Configuration
@ContextConfiguration(locations = {"classpath:spring/spring-dao.xml","classpath:scan.xml"} ) 
public class bbsConfig{
    private Postdao postdao;
    private Userdao userdao;
    @Bean(name="postservice")
 public PostService getPost()
    {
    return new PostserviceImpl(postdao,userdao);
    }

When bean is injected into PostService, two bean, postdao and userdao are relied on at the same time. Just refer to beanID directly, and spring will automatically get these bean from the container as long as they are configured correctly. In this example, userdao and postdao are configured by Mybatis to inject dao interface generation agent into spring, which can actually be regarded as xml assembling bean. You can refer to this article, which is quite clear. https://www. ofstack. com/article/157618. htm

If another bean is declared here, the postserviceImpl object will still be returned, which is exactly the same as the previous bean and is the same instance. If spring @ bean is the same beanID, it returns a singleton bean by default and injects the same instance. If you modify one of them, they will all change.

However, it should be noted here that when testing, because the unit test of spring and the container of springIoc are completely independent, postdao and userdao inject detection uses locations to load xml file, while postservice uses classes to load config class, but the two cannot be mixed in @ ContextConfiguration at the same time. So if you have to test them all, test them separately.

Type 3:

Assembling bean in 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
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context">
 <import resource="spring/spring-dao.xml"/>

 <bean id="postservice" class="com.bbs.service.impl.PostserviceImpl">
  <constructor-arg ref="postdao"/>
  <constructor-arg ref="userdao"/>
 </bean>
</beans>

When configuring bean of postservice, two bean, postdao and userdao need to be introduced into the label of constructor-arg, and ref refers to ID of dependent bean. If configured in javaConfig, write the contents of @ Bean. If it is @ Component, write the content of @ Qualifier. bean of dao interface is introduced here, which is configured in spring-dao. xml. beanID can be automatically obtained by introducing this configuration file.

Mix 3 assemblies:

1. You can use the @ import(bbsConfig.class) Combine other java annotations

2. Use the @ imortResource("classpath:spring-dao.xml") Combine other xml annotations

3. You can use the @ContenxtConfiguration Contains class or xml

4. In xml, you can use the <import resource="spring-dao.xml"> Introduces xml annotations, and can also use <bean class="com.bbs.dao.Userdao"> Introducing java annotations

Summarize


Related articles: