@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);
}
}
}
打印运行结果:
我们可以看到,最终得到的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);
}
}
}
运行结果:
可以看到实例化后就会执行initmethod方法,这里我还添加了一个InitializationBean接口,大家可以观察他们的执行顺序。