Assembling beans from Java code

The above has combed through the annotations to implicitly complete the scanning and automatic assembly of components. Let's learn how to assemble beans through explicit configuration.

2. Assembling beans through Java classes

The HelloWorldConfig class is defined in the front and annotated with @ComponentScan and @Configuration . The @Configuration annotation indicates that this class is a java configuration class. This class is used to obtain the Spring application context to tell Spring the details of bean creation. Through @ComponentScan , We have enabled Spring's automatic component scanning. Now let's see if we configure beans explicitly through java classes. Let's practice it through an example of a music player.

To play music, we first need a player, and then we need music resources. First, we define a player interface and a music resource interface.

package com.seven.springTest.service;

// 播放器
public interface MediaPlayer { void play(); }
package com.seven.springTest.service;

// 音乐资源
public interface MusicSource { void play(); }

This time to play music, we use the CD-ROM drive to play CD music. Let's implement the above interface.

package com.seven.springTest.service.impl;

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

import com.seven.springTest.service.MusicSource;
import com.seven.springTest.service.MediaPlayer; //定义光驱播放器 public class CDPlayer implements MediaPlayer { @Autowired // 定义一个音乐资源,这里通过@Autowired来声明需要注入MusicSource的依赖 private MusicSource cd ; @Override public void play() { //播放音乐 cd.play(); } } 

Implementing music resources as discs

package com.seven.springTest.service.impl;
import com.seven.springTest.service.MusicSource;

public class CDSource implements MusicSource { private String title = "七里香"; private String artist = "周杰伦"; @Override public void play() { System.out.println("Playing " + title + " by " + artist); } }

So far we have completed the interface definition and specific implementation of the player and music resources, so if we tell Spring which beans should be created and what dependencies should be injected for them? In the first part, we told Spring implicitly via @Component annotation , now we configure bean components via java classes.

@Bean

The @Bean annotation tells Spring that the function will return an object that needs to be registered as a bean in the Spring application context, and that method contains the logic to generate a bean instance

package com.seven.springTest.Configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import com.seven.springTest.service.MusicSource; import com.seven.springTest.service.MediaPlayer; import com.seven.springTest.service.impl.CDPlayer; import com.seven.springTest.service.impl.CDSource; @Configuration public class MediePlayerConfig { @Bean //该方法返回的MusicSource对象需要注册为Spring应用上下文中的bean public MusicSource cdsource(){ return new CDSource(); } @Bean //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean public MediaPlayer cdplayer(){ return new CDPlayer(); } }

In the MediePlayerConfig class, we only added the @Configuration annotation . The previous @ComponentScan annotation was removed , and there was no configuration to start Spring's component scanning. In addition, the implementation class of the interface did not add the @Component annotation . We use the @Bean annotation to tell Spring which Objects need to be registered as beans in the Spring application context . The cdsource() method returns an instance object CDSource of type MusicSource, which is registered in the Spring application context, and the same cdplayer() method returns an instance of MediaPlayer type CDPlayer is registered in the Spring application context. Let's test it

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.Configuration.MediePlayerConfig;
import com.seven.springTest.Configuration.HelloWorldConfig;
import com.seven.springTest.service.MediaPlayer; public class MediaPlayerTest { public static void main(String[] args) { //加载java配置类获取Spring应用上下文 ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class); //获取播放器 MediaPlayer player= ac.getBean(MediaPlayer.class); //播放 player.play(); } }

When we get the player bean, what we actually get is the object CDPlayer returned by cdplayer() in the MediePlayerConfig class. In CDPlayer, we rely on MusicSource. Through the @Autowired annotation , Spring automatically injects the bean with a dependency on MusicSource, so In the test code, we only get the instance player of the MediaPlayer object. As for the dependencies of the player, we don’t know. They are all injected by the Spring container. We only care about the player here. This is what Spring brings us. Convenient, we don't need to use code to manage the dependencies of the object, all the resources that the object depends on are injected by the Spring container for us.

With the development of technology, one day the optical drive can also be inserted into the U disk to play MP3 music. At this time, we will realize an MP3 music resource.

package com.seven.springTest.service.impl;

import com.seven.springTest.service.MusicSource;

public class MP3Source implements MusicSource { private String title = "外婆"; private String artist = "周杰伦"; @Override public void play() { // TODO Auto-generated method stub System.out.println("MP3 Playing " + title + " by " + artist); } }

In the first part of autowiring, if Spring finds multiple beans to satisfy dependencies, Spring cannot choose. If we define the implementation of MP3Source, will this happen now? By running the program, we found that it did not have any effect, the MusicSource dependency of the CDPlayer bean injected was still CDSource. This is because we informed Spring of the implementation logic of bean generation through cdsource() in MediePlayerConfig, so let's modify cdsource()

@Bean   //该方法返回的MusicSource对象需要注册为Spring应用上下文中的bean
public MusicSource cdsource(){ //返回MP3Source实例 return new MP3Source(); }

We ran the test method again and found that the output content became "==MP3 Playing Grandma by Jay Chou==", indicating that the implementation of the injected dependency object has changed, because the implementation of cdsource() is to return the instance of MP3Source.

Like the previous @Component , the bean returned by the method annotated with @Bean will also be assigned an ID by default, which is the same as the method name by default. For example, the ID of the bean returned by the cdsource() method is "cdsource", we can also Specify the ID of the bean, as follows:

@Bean(name="myCdplayer")      //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(){ return new CDPlayer(); }

In this way, when you get the bean, you can get it by ID

public class MediaPlayerTest {
    public static void main(String[] args) { //加载java配置类获取Spring应用上下文 ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class); //根据ID获取bean MediaPlayer player= (MediaPlayer) ac.getBean("myCdplayer"); //播放 player.play(); } }

In the above case, the CDPlayer bean depends on the dependency of MusicSource. We declare the dependencies required by CDPlayer through @Autowired in the CDPlayer class . Here is an implicit configuration through annotations. Let's implement it through the java configuration class.

If it is an explicit configuration, since the beans configured in MediePlayerConfig are returned through methods, you need to inject dependencies in the method that returns the object bean:

@Bean(name="myCdplayer")  //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(){ return new CDPlayer(cdsource()); //通过对象的构造函数注入依赖 }

or

@Bean(name="myCdplayer")  //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(MusicSource musicSource){ return new CDPlayer(musicSource); //通过对象的构造函数注入依赖 }

Through the configuration in the above 2 ways, Spring can complete dependency injection for the MusicSource object in CDPlayer. Next, we define a bean configuration

@Bean(name="myCdplayer")  //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(){ return new CDPlayer(cdsource()); //通过对象的构造函数注入依赖 } @Bean(name="otherCdplayer") //定义另外一个bean对象, public MediaPlayer othercdplayer(){ return new CDPlayer(cdsource()); } 

The MediaPlayer interface adds a method to obtain playback resources

package com.seven.springTest.service;

public interface MediaPlayer {

    /**
    * 获取播放器加载的资源 
    * @return MusicSource
    */
    MusicSource getResource(); /** * 播放 */ void play(); }

Solve the following, we modify the Test code

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.Configuration.MediePlayerConfig;
import com.seven.springTest.Configuration.HelloWorldConfig;
import com.seven.springTest.service.MediaPlayer; public class MediaPlayerTest { public static void main(String[] args) { // 加载java配置类获取Spring应用上下文 ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class); // 获取播放器 MediaPlayer player = (MediaPlayer) ac.getBean("myCdplayer"); MediaPlayer otherplayer = (MediaPlayer) ac.getBean("otherCdplayer"); if (player.getResource().equals(otherplayer.getResource())) { System.out.println("true"); } // 播放 //player.play(); } }

After running, we found the output "true", what does this mean? When we call CDPlayer(cdsource()) in the cdplayer() and othercdplayer() methods, the music resource objects obtained through cdsource() are the same Yes, by default, the beans in Spring are singletons. Spring will intercept the call to cdsource() and ensure that the returned bean is the bean created by Spring, that is, Spring itself calls cdsource() for the first time. created bean.

 

Guess you like

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