Concept understanding:
Automatic assembly: Spring uses dependency injection (DI) to complete the assignment of dependencies on each component in the IOC container;
span>
You can use the @Autowired annotation to achieve automatic injection, here we omit some simple bean Create, The sample code is as follows:
BookService.java
@Service
public class BookService {
@Autowired
private BookDao bookdao;
@Override
public String toString() {
return "BookService [bookdao=" + bookdao + "]";
}
}
BookDao.java
@Repository
public class BookDao {
}
Test method:
@Test
public void test02() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigAutoware.class< span style="color: #000000;">);
BookService bookService = applicationContext.getBean(BookService.class);
System.out.println(bookService);//Print out the BookDao object in BookService
BookDao bookDao = applicationContext.getBean(BookDao.class);
System.out.println(bookDao);//Print out the BookDao object in the container
applicationContext.close(); //Close the container< /pre>}
Run results
BookService [bookdao=[email protected]]
[email protected]
It can be seen from the above running results: the bean in the container and the bean automatically injected into the BookService are the same [email protected] ] The working principle of @AutoWired annotation is that if a bean in a container is referenced in a certain class, you can add @Autowired annotation to the attribute of the class.
Then @AutoWired prefers to go according to the type by default. Find the corresponding component in the container.
In this case, when there is only one bean object in the container, If multiple components of the same type are found, Spring will throw An error
expected single matching bean but found 2: bookDao,bookDao2
For this type of finding multiple Bean objects, you can use @Qualifier("specified id name") to specify which bean instance code is used as follows:
@Service
public class BookService {
@Qualifier("bookDao")//Specify to load "bookDao"
@Autowired
private BookDao bookdao;
@Override
public String toString() {
return "BookService [bookdao=" + bookdao + "]";
}
}
At this time, the error will disappear; the bookDao object will be loaded in the container;
Another solution is to use @ Primary annotation, this annotation is loaded under the @Bean annotation of the configuration class, meaning that when there are two beans of the same type, take the bean object marked by @Primary
The configuration class code is as follows:
@Configuration
@ComponentScan({"com.wxj.service","com.wxj.dao"})
public class MainConfigAutoware {
@Primary
@Bean("bookDao2")
public BookDao bookDao() {
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}
Change BookDao class
@Repository
public class BookDao {
private String lable = "1";
public String getLable() {
return lable;
}
public void setLable(String lable) {
this.lable = lable;
}
@Override
public String toString() {
return "BookDao [lable=" + lable + "]";
}
}
Run test results:
BookService [bookdao=BookDao [lable=2]]
The bean marked by @Primary is loaded in the container.
Note:If @Qualifier and @Primary annotations are used at the same time, the bean specified by @Qualifier is preferred;
There is another case that there is no such type in the container bean, running the test class will report an error:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} p>
According to the prompt of the Spring container, you can see that if the @AutoWired annotation is used in the class to achieve automatic assembly, then there will be at least one in the container This type of bean. So how to solve the problem? You can specify the required attribute of @Autowired to indicate that the object will be loaded if it has it, and it will not be loaded if it is not
@Autowired(required=true): By default, there must be beans annotated by @Autowired in the container,
@Autowired(required=false): It means that if there is a specified bean in the container, it will be loaded, if not, it will not be loaded.
@Service
public class BookService {
@Autowired
private BookDao bookdao;
@Override
public String toString() {
return "BookService [bookdao=" + bookdao + "]";
}
}
@Repository
public class BookDao {
}
@Test
public void test02() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigAutoware.class< span style="color: #000000;">);
BookService bookService = applicationContext.getBean(BookService.class);
System.out.println(bookService);//Print out the BookDao object in BookService
BookDao bookDao = applicationContext.getBean(BookDao.class);
System.out.println(bookDao);//Print out the BookDao object in the container
applicationContext.close(); //Close the container< /pre>}
BookService [bookdao=[email Protected]]
[email protected]@Service
public class BookService {
@Qualifier("bookDao")//Specify to load "bookDao"
@Autowired
private BookDao bookdao;
@Override
public String toString() {
return "BookService [bookdao=" + bookdao + "]";
}
}@Configuration
@ComponentScan({"com.wxj.service","com.wxj.dao"})
public class MainConfigAutoware {
@Primary
@Bean("bookDao2")
public BookDao bookDao() {
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}@Repository
public class BookDao {
private String lable = "1";
public String getLable() {
return lable;
}
public void setLable(String lable) {
this.lable = lable;
}
@Override
public String toString() {
return "BookDao [lable=" + lable + "]";
}
}BookService [bookdao=BookDao [lable=2]]