[springboot注解 容器篇] @Bean

@Bean
前面说了@Configuration注解就相当于让一个类变成了spring的configuration.xml的作用,那么有了配置文件,怎么注入bean呢?这就需要@Bean这个注解,这个注解用于方法上,当方法上加上@Bean就相当于在xml中加入了一个<bean>标签。

下面先来看一个例子,然后在详细介绍

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +"name='" + name + '\'' +'}';
    }
}
package com.lhb.config;

import com.lhb.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration // 相当于写了一个spring的xml配置文件
public class MyConfig {
    @Bean // 相当于在xml配置文件中的bean标签注册一个bean,类型就是返回值类型,id默认就是方法名
    public Person person(){
        // 相当于给xml中bean标签的对象配置属性
        Person person = new Person();
        person.setName("john");
        return person;
    }
}
package com.lhb;

import com.lhb.bean.Person;
import com.lhb.config.MyConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppliactionRunner {
    public static void main(String[] args) {
// 当使用注解时,就要使用AnnotationConfigApplicationContext,他会将@Configuration注解的类中的@Bean注解的返回对象都放到容器中。
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        Person person = applicationContext.getBean(Person.class);
        System.out.println(person); // Person{name='john'}
    }
}

我们知道在以前使用xml配置bean的时候,bean都会有id和name,当我们使用@Bean注解是,默认方法的名字就是bean的name。看下面的例子:

@Configuration // 相当于写了一个spring的xml配置文件
public class MyConfig {
    @Bean
    public Person person(){
        // 相当于给xml中bean标签的对象配置属性
        Person person = new Person();
        person.setName("john");
        return person;
    }

    @Bean
    public Person person01(){
        // 相当于给xml中bean标签的对象配置属性
        Person person = new Person();
        person.setName("john");
        return person;
    }
}
public class AppliactionRunner {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] names = applicationContext.getBeanNamesForType(Person.class);
        for (String name : names) {
            System.out.println(name); // person person01
        }
    }
}

我们通过getBeanNamesForType()方法就可以只当注入到容器中的某个类型的bean的name了,我们前面说过这个name的默认值就是@Bean所在的方法的名字,因为我们定义了两个bean,所以最后打印出两个名字。

那么假如现在如果不想让这个方法的名字作为bean默认的name值,怎么办呢?一种方式是直接修改方法名,一种方式我们可以在@Bean注解中来设定,如下:

方式一:通过修改方法名来修改bean的name值

@Configuration // 相当于写了一个spring的xml配置文件
public class MyConfig {
    @Bean
    public Person person01(){
        // 相当于给xml中bean标签的对象配置属性
        Person person = new Person();
        person.setName("john");
        return person;
    }
}
public class AppliactionRunner {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] names = applicationContext.getBeanNamesForType(Person.class);
        for (String name : names) {
            System.out.println(name); //person01
        }
    }
}

方式二:通过@Bean注解来修改

@Configuration
public class MyConfig {
    @Bean("personName")
    public Person person(){
        Person person = new Person();
        person.setName("john");
        return person;
    }
}
public class AppliactionRunner {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] names = applicationContext.getBeanNamesForType(Person.class);
        for (String name : names) {
            System.out.println(name);// personName
        }
    }
}

下面我们来看一下@Bean中其他属性的作用:

例子1:注入两个相同类型的bean,但是有一个使用了value属性

package com.lhb.config;

import com.lhb.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration // 相当于写了一个spring的xml配置文件
public class MyConfig {
    @Bean(value = { "person1"})
    public Person person(){
        // 相当于给xml中bean标签的对象配置属性
        Person person = new Person();
        person.setName("john");
        return person;
    }

    @Bean
    public Person person1(){
        // 相当于给xml中bean标签的对象配置属性
        Person person = new Person();
        person.setName("john1");
        return person;
    }
}

运行main方法

public class AppliactionRunner {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(applicationContext.getBean(Person.class));
        String[] names = applicationContext.getBeanNamesForType(Person.class);
        for (String name : names) {
            System.out.println(name);
        }
    }
}

打印运行结果:
[springboot注解 容器篇] @Bean

 我们可以看到,最终得到的bean时使用了value属性的那个bean,我们知道要给一个bean修改他的name属性的值,一种方式是通过方法名,一种是通过在@Bean中使用value或者name属性。这里我们同事使用2中方式修改成同一个名字,发现最终使用的是由value值的,这就类似于在xml中设置了多个bean时,当哪个bean中设置了primary属性,哪个最终将被使用一样。
另外注意:@Bean中的name和value属性不能同时使用只能使用一个。

实例2:@Bean的init-method属性

package com.lhb.bean;

import org.springframework.beans.factory.InitializingBean;

public class Person implements InitializingBean {
    private String name;
    public Person(String name) {
        System.out.println("i am constructor");
        this.name = name;
    }
    public void initMehod(){System.out.println("i am init.....");}

    // InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("i am InitalizaingBean‘s afterPropertiesSet");
    }

    @Override
    public String toString() { return "Person{" +"name='" + name + '\'' +'}'; }
}
@Configuration // 相当于写了一个spring的xml配置文件
public class MyConfig {
    @Bean(initMethod="initMehod")
    public Person person(){
        Person person = new Person("john");
        return person;
    }
}
public class AppliactionRunner {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(applicationContext.getBean(Person.class));
        String[] names = applicationContext.getBeanNamesForType(Person.class);
        for (String name : names) {
            System.out.println(name);
        }
    }
}

运行结果:
[springboot注解 容器篇] @Bean

可以看到实例化后就会执行initmethod方法,这里我还添加了一个InitializationBean接口,大家可以观察他们的执行顺序。

上一篇:Ternary Expression Parser


下一篇:uniapp返回上一页携带参数,两种方法,实测有效