Autowire Beans

1. Spring assembly - automated assembly

@Component和@ComponentScan

The spring annotation (@Component) is used to indicate that this class will be used as a component class, and Spring is told to create beans for this class, but component scanning is not started by default, and Spring needs to be explicitly configured, so as to instruct Spring to find a bean with ( @Component) annotated class and create a bean for it.

1. Define the interface

package com.seven.springTest.service;

public interface HelloWorldApi { public void sayHello(); } 

2. Define the implementation class of the interface

package com.seven.springTest.service.impl; import org.springframework.stereotype.Component; import com.seven.springTest.service.HelloWorldApi; @Component //通过注解指定该类组件类,告知spring要为它创建Bean public class PersonHelloWorld implements HelloWorldApi { @Override public void sayHello() { System.out.println("Hello World,This Is Person!"); } }

3. As mentioned earlier, spring does not automatically enable component scanning, and requires explicit configuration. Here, the explicit configuration is performed through the java class, and the java configuration class HelloWorldConfig is defined. In the configuration class, we do not explicitly declare any bean, just using the @ComponentScan annotation to enable component scanning

package com.seven.springTest;

import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan // 启用组件扫描 public class HelloWorldConfig { } 

Now that all the work is done, let's test

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.HelloWorldConfig;
import com.seven.springTest.service.HelloWorldApi;

public class HelloWorldTest { public static void main(String[] args) { //1. 声明Spring上下文,采用java配置类 ApplicationContext ac = new AnnotationConfigApplicationContext(HelloWorldConfig.class); //2. 声明Spring应用上下文,采用xml配置 //ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml"); //通过Spring上下文获取Bean,在这里Spring通过自动扫描发现了PersonHelloWorld的实现,并自动创建bean。 HelloWorldApi hwapi = ac.getBean(HelloWorldApi.class); //通过sayHello()的输入内容可以看到,hwapi为PersonHelloWorld的实例 hwapi.sayHello(); } }

Through the above code, the following content will be output in the console "Hello World, This Is Person!"

The Spring container found the PersonHelloWorld class through component scanning and created a corresponding bean for it. So far, we have realized automatic assembly through simple annotations. In the above case, if the HelloWorldConfig configuration class @ComponentSan has no other configuration , it will only scan the package where HelloWorldConfig is located or its subpackages. If you need to specify the package to scan, you can pass

@ComponentScan("com.seven.springTest")

or

@ComponentScan(basePackages="com.seven.springTest")

basePackages allows to set multiple packages, just set the basePackages familiar to an array

@ComponentScan(basePackages={"com.seven.springTest.service","com.seven.springTest.impl"})

In addition to setting Spring to enable component scanning through the java configuration class, it is also possible to configure it explicitly through the xml class, refer to the xml configuration below, and initialize it through xml when obtaining the Spring application context.

<?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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 启用Spring组件扫描--> <context:component-scan base-package="com.seven.springTest"></context:component-scan> </beans>

In the above case, we implicitly configure the Bean assembly through @Component and @ComponentScan . Next, we will discuss @Component and @ComponentScan in depth.

When the Spring container manages beans, it will give each bean an ID. In the above example, if there are multiple implementation classes of HelloWorldApi, how should the Spring container allocate beans? If we use @Component , there is no Explicitly set an ID for PersonHelloWorld, the Spring container will give the bean an ID by default, usually the class name (the first letter will be lowercase, such as running personHelloWorld), so the following code is also valid

//通过bean的ID来获取实例
HelloWorldApi hwapi = (HelloWorldApi) ac.getBean("personHelloWorld");
hwapi.sayHello();

At the same time, we can also set the ID for the bean, as follows:

@Component("person")    //为bean设置ID为“person”
public class PersonHelloWorld implements HelloWorldApi { @Override public void sayHello() { // TODO Auto-generated method stub System.out.println("Hello World,This Is Person!"); } }

In this way, when we get the bean, we can get it by ID, as follows:

// 根据设置的bean ID来获取bean
HelloWorldApi hwapi = (HelloWorldApi) ac.getBean("person");

In the above case, we used @Component and @ComponentScan to implement component scanning . So far, we have been operating on a single object. If the program is complicated and there are dependencies between objects, how to deal with it? Next, let's study how to add annotations to beans to achieve automatic assembly

@AutoWired

In the above case, Person said Hello to the whole world, but only the people next to him know what he said. We need to let more people hear our "hello world". We need some tools. We can use TV to broadcast. Let more people hear it, first we define a communication tool interface

package com.seven.springTest.service;

public interface TransmittingTool { void work(String message); }

Next let's create our TV

package com.seven.springTest.service.impl;
import org.springframework.stereotype.Component;

import com.seven.springTest.service.TransmittingTool;

@Component   //设置为需要被扫描到的组件 public class TVTool implements TransmittingTool { @Override public void work(String message) { //传播工具工作,把我们的消息传播出去 System.out.println(message); } }

Next we need to make some modifications to the sayHello() method of our previous PersonHelloWorld so that it can say Hello to the world through the dissemination tool

package com.seven.springTest.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.seven.springTest.service.HelloWorldApi;
import com.seven.springTest.service.TransmittingTool; @Component public class PersonHelloWorld implements HelloWorldApi { //定义传播工具 @Autowired //1.直接变量添加注解 private TransmittingTool transmittingTool; // @Autowired //2. 通过构造函数注入依赖 // public PersonHelloWorld(TransmittingTool transmittingTool) { // this.transmittingTool = transmittingTool; // } // @Autowired //3. 通过属性的Setter方法注入依赖 // public void setTransmittingTool(TransmittingTool transmittingTool) { // this.transmittingTool = transmittingTool; // } // @Autowired //4. 通过其他函数注入依赖 // public void inserttool(TransmittingTool transmittingTool){ // this.transmittingTool=transmittingTool; // } @Override public void sayHello() { // 通过传播工具来sayHello transmittingTool.work("Hello World,This Is Person!--form TV"); } }

First of all, we define a propagation tool. We don't know the specific implementation of this tool. We need the Spring container to inject dependencies for me.
@Autowired can be used directly on class variables, constructors, Setters and any other methods, refer to the implementation of 1-4 in the code

  1. Add annotations directly to variables
  2. Add annotations to the constructor. When the spring container instantiates the bean through the constructor, it will pass in an instance provided to the transmittingTool to inject dependencies;
  3. Through the Setter method or other functions, Spring will try to satisfy all the dependencies of the bean after initializing the bean. If the fourth injection is used, we have not called the inserttool() method in HelloWorldTest again, but sayHello() is still If it can be executed normally, Spring will try to inject the dependencies of PersonHelloWorld according to @Autowired .

If a dependency that meets the requirements can be configured, the dependent bean will be assembled. If there is no matching dependent bean, Spring will throw an exception when the application context is created. In order to avoid exceptions, we can Set @Autowired's required to false ;

@Autowired(required=false)   //2. 通过构造函数注入依赖
public PersonHelloWorld(TransmittingTool transmittingTool) { this.transmittingTool = transmittingTool; } 

After the required of @Autowired is set to false, Spring tries to autowire the bean and inject dependencies. If there is no matching bean, Spring will leave the bean in an unassembled state. When setting required to false, you need to pay attention. Because the dependent bean is in the unassembled state, when calling the dependency, if your code does a null check, the property in the unassembled state may have an exception.

Spring will also throw an exception if there are multiple beans that satisfy the dependency, indicating that it is not clear which bean to choose for autowiring. I will open a separate article explaining Spring's advanced assembly later, and I will explain it in detail at that time. You can pay attention to the follow-up articles.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325087274&siteId=291194637