The configuration of spring bean asked by my sister is often used. I used the most easy to understand explanation to let her learn

Time:2020-6-9

Hello, I’m silence Wang Er, an interesting programmer. I’ve been writing articles full of spirit and strive to be fresh and refined. Yesterday I went to the millet shop in Wangfujing and ordered a millet 10. I said it would arrive in a week, but I can’t help but want to see her today. Seeing that I don’t think about tea and rice, my wife advised me to go and write your article instead of thinking about it. So there is today’s “common configuration of spring bean”, in the form of a dialogue between me and my three younger sisters.

Teach my sister Java, haven’t you seen such a bold title? It’s true that the title of this article is so cool, otherwise how could you point in?

I have a beautiful sister (see the picture above). What’s her name? I think smart readers can guess: silence King three, yes, three or six years old. My parents are thinking of letting her learn from me and become a serious java programmer. I was against it at the beginning, because programmers are prone to lose their hair. But it’s hard for her family. Instead of opposing it, it’s better to do something more positive, such as writing some interesting articles to teach her.

“Second brother, I have a strong feeling that spring is really powerful, just like the Buddha’s noodles in the spring breeze, like learning the next chapter.”

“Ah, three younger sister, although your metaphor is somewhat farfetched, it is more or less poetic.”

“Well, let’s start today’s study!”

01. Scope configuration of bean

“Second brother, it is said that there are several types of bean scope, which are used to define the bean’s life cycle and usage environment. Can you tell me more about them?”

“No problem.”

1)singleton

That is, single instance mode. If a bean’s scope is defined as a singleton, it means that an instance will only be created once in the spring container, and any changes to the instance will be reflected in its references. This is also the default configuration item of scope, which can be omitted.

To create a new writer class, the contents are as follows:

public class Writer {    private String name;    public Writer() {    }    // getter setter}

Then create a singletonconfig class, as follows:

@Configurationpublic class SingletonConfig {    @Bean    @Scope("singleton")    public Writer getWriterSingleton() {        return new Writer();    }}

@ConfigurationThe annotation indicates that the current class is a configuration class, which is equivalent to an XML file configured by spring.

@BeanNotes used ingetWriterSingleton()Method, indicating that the current method returns a bean object (writer), and then submits it to spring management.

You can use spring defined constants instead of the string singleton:

@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)

Of course, it can also be completely omitted, so singleton config is slimming down.

@Configurationpublic class SingletonConfig {    @Bean    public Writer getWriterSingleton() {        return new Writer();    }}

Create a new singletonmain class with the following code:

public class SingletonMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( SingletonConfig.class );        Writer writer1 =  context.getBean ( Writer.class );        Writer writer2 =  context.getBean ( Writer.class );          System.out.println (writer1);         System.out.println (writer2); writer1.setname ("silence King II") System.out.println (writer2.getName());         context.close ();    }}

The output of the program is as follows:

commonuse.singleton.Writer @19dc67c2 commonuse.singleton.Writer @19dc67c2 silence King II

The string representation of writer1 and writer2 are exactly the same, both of them are[email protected]; in addition, when the name of the writer1 object is changed, the writer2 also changes.

From the results, we can draw the conclusion that when scope is singleton, we can usegetBean()Got writer instances twice, but they are the same object. As long as you change the state of any one of them, the other will change at the same time.

2)prototype

The English meaning of prototype is plural. It means that a bean will create multiple instances in spring, which is suitable for multithreading scenarios.

Create a prototypeconfig class, as follows:

@Configurationpublic class PrototypeConfig {    @Bean    @Scope("prototype")    public Writer getWriterPrototype() {        return new Writer();    }}

You can use spring defined constants instead of the string prototype:

@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Create a new prototypemain class with the following code:

public class PrototypeMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( PrototypeConfig.class );        Writer writer1 =  context.getBean ( Writer.class );        Writer writer2 =  context.getBean ( Writer.class );          System.out.println (writer1);         System.out.println (writer2); writer1.setname ("silence King II") System.out.println (writer2.getName());         context.close ();    }}

The output of the program is as follows:

[email protected]@dd3b207null

The string representation of writer1 and writer2 are totally different. One is[email protected], the other is[email protected]; in addition, although the name of the writer1 object is changed to “silent King II”, the name of writer2 is still null.

From the result, we can draw the conclusion that when scope is prototype, every time we callgetBean()Will return a new instance, they are not the same object. Changing the state of any one of them does not change the other at the same time.

3)request、session、application、websocket

These 4 scopes are only available in the context of Web applications and are not commonly used in practice. Request is used to create a bean instance for HTTP requests, session is used to create a bean instance for HTTP sessions, application is used to create a bean instance for ServletContext, and websocket is used to create a bean instance for a specific websocket session.

02. Bean field injection

“Second brother, it is said that spring development often involves calling various configuration files, which need to be used@ValueAnnotation, can you tell me more about it? “

“No problem.”

1) Inject normal string

To create a valueconfig class, the contents are as follows:

@Configurationpublic class valueconfig {@ value ("silent King 2") private string name; public void output() { System.out.println (name);    }}

@ValueThe annotation is used on the member variable name to indicate that the current value of injected name is “silence King II”.

To create a valuemain class, the contents are as follows:

public class ValueMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpELStringConfig.class);        SpELStringConfig service = context.getBean(SpELStringConfig.class);        service.output();        context.close();    }}

The output of the program is as follows:

Silence King II

The results are in line with our expectations.

2) Inject spring expression

use@ValueThe way to inject ordinary strings is the simplest. Let’s upgrade it and inject spring expressions. Let’s start with an addition operation.

@Value("#{18 + 12}") // 30private int add;

Need to use in double quotes#{}。 Let’s have another relational and logical operation.

@Value("#{1 == 1}") // trueprivate boolean equal;@Value("#{400 > 300 || 150 ) // trueprivate boolean or;

I don’t think it’s exciting enough. Let’s do another ternary operation.

@Value ("{2 > 1? 'silence is gold': 'no more silence'}") / "silence is gold" private string yesterday;

3) Injection profile

If you don’t think that’s interesting enough, inject the configuration file.

Create a new one in the resources directory value.properties The contents of the document are as follows:

Name = silence King II age = 18

Create a new valuepropertiesconfig class, as follows:

@ [email protected] (" classpath:value.properties ")public class ValuePropertiesConfig {    @Value("${name}")    private String name;    @Value("${age}")    private int age;    public void output() {         System.out.println ("Name:" + name + "age:" + age);}}} "

@PropertySourceAnnotations are used to specify which profile to load( value.properties ),classpath:Indicates to search from SRC or resources directory.

Pay attention to this@Value("")The double quotation marks of are the $sign instead of the X sign,{}Is the key in the configuration file.

Create a new valuepropertiesmain class, as follows:

public class ValuePropertiesMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ValuePropertiesConfig.class);        ValuePropertiesConfig service = context.getBean(ValuePropertiesConfig.class);        service.output();        context.close();    }}

The running results of the program are as follows:

Name: 3, age: 18

“No, second brother! The Chinese code is out of order! “

“Don’t be afraid, three younger sisters. The problem is easy to solve.”

First, look at how the properties file is encoded.

If it is not UTF-8, it will be changed to UTF-8. At the same time, make sure that there is no Chinese scrambling in the properties file after modifying the encoding method.

Then, at@PropertySourceThe coding format is added to the annotation.

@PropertySource(value = "classpath:value.properties",  encoding = "UTF-8")

After running the program again, the code was blown away by the wind.

Name: silent Wang Er age: 18

03. Initialization and destruction of bean

“Second brother, it is said that in actual development, it is often necessary to add some extra operations during bean initialization and destruction. Can you tell me how to implement it in detail?”

“No problem.”

1)init-method/destroy-method

Create a new initdestroyservice class, as follows:

public class InitDestroyService {    public InitDestroyService() {         System.out.println ('constructor');} public void init() { System.out.println ("initialization");} public void destroy { System.out.println (destroy);}}

InitDestroyService()For the construction method,init()To initialize a method,destroy()Is the destruction method.

Create a new initdestroyconfig class, as follows:

@Configurationpublic class InitDestroyConfig {    @Bean(initMethod = "init",destroyMethod = "destroy")    public InitDestroyService initDestroyService() {        return new InitDestroyService();    }}

@BeanAnnotatedinitMethodUsed to specify the method of bean initialization,destroyMethodSpecifies the method when the bean is destroyed.

Create a new initdestroymain class, as follows:

public class InitDestroyMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( InitDestroyConfig.class );        InitDestroyService service =  context.getBean ( InitDestroyService.class );          System.out.println ("ready to close container") context.close ();    }}

The running results of the program are as follows:

Constructor initialization ready to close container destroy

That is, the initialization method executes after the method is constructed, and the destruction method executes after the container is closed.

2)@PostConstruct/@PreDestroy

Create a new initdestroyservice class, as follows:

public class InitDestroyService {    public InitDestroyService() {         System.out.println ('constructor');} @ postconstruct public void init() { System.out.println ('initialize');} @ predestroy public void destroy() { System.out.println ("destruction");     }}

@PostConstructThe role of annotations and@BeanInit method has the same function in the annotation, which is used to specify the method to execute after bean initialization.

@PreDestroyThe role of annotations and@BeanThe destroymethod in the annotation has the same function, which is used to specify the method to execute after the bean is destroyed by the container.

Create a new initdestroyconfig class, as follows:

@Configurationpublic class InitDestroyConfig {    @Bean    public InitDestroyService initDestroyService() {        return new InitDestroyService();    }}

@BeanInit method and destroymethod parameters no longer need to be specified in the annotation.

Create a new initdestroymain class, as follows:

public class InitDestroyMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( InitDestroyConfig.class );        InitDestroyService service =  context.getBean ( InitDestroyService.class );          System.out.println ("ready to close container") context.close ();    }}

The running results of the program are as follows:

Constructor initialization ready to close container destroy

The results are in line with our expectations.

04. Configure different environments for bean

“Second brother, it’s said that in spring development, beans often need to be switched to different environments, such as development environment, test environment and formal production environment. Can you tell me how to implement it?”

“No problem.”

To consider such a common scenario, we need to configure different data sources for the development environment and the formal production environment.

Create a new datasource class, as follows:

public class Datasource {    private String dburl;    public Datasource(String dburl) {        this.dburl = dburl;    }    // getter/setter}

Dbname is used to specify the connection address of databases in different environments.

Create a new Config class, as follows:

@Configurationpublic class config {@ bean @ profile ("dev") public datasource devdatasource() {return new datasource ("development environment");} @ bean @ profile ("prod") public datasource proddatasource() {return new datasource ("formal production environment");}}

@ProfileAnnotations are used to identify the beans to be instantiated in different environments.

Create a new main class, as follows:

public class Main {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();        ConfigurableEnvironment environment = context.getEnvironment();        environment.setActiveProfiles("prod");        context.register(Config.class);        context.refresh();        Datasource datasource = context.getBean(Datasource.class);        System.out.println(datasource.getDburl());        context.close();    }}

Do not specify configuration class when creating annotationconfigpplicationcontext object, wait until callingsetActiveProfiles("prod")Method to set the environment to the formal production environment before passingregister(Config.class)Method to register the configuration class into the container, and remember to refresh the container.

Run the program and output the following:

Formal production environment

Then change “prod” to “dev”, run the program again, and output the following:

development environment 

“Second brother, have you uploaded the sample code in this article to the code cloud? Recently, GitHub has a little bit of a card to visit. “

“It’s very kind of you, third sister. Code cloud portal ~ “

“Second brother, you teach very well. I’ve learned it completely. It’s not boring at all.”

“That must be, looking forward to the next one?”

“Of course, I’m looking forward to it. I’m looking forward to it.”

Please make complaints about it. I don’t want to be fired again. I want to see if I encourage you to do so much more than creativity. Dry cargo + fun.Don’t look at it. Praise it. You’re the most beautiful. You’re the most handsome

If you think the article will help you a little, please search on wechatSilence King II“Read at the first time, reply【666】【1024】What’s more, I have prepared 500g high-definition teaching video for you (which has been classified) and a copy of the manual compiled by the technical talents of Daichang.