@Bean

@Bean标识一个用于配置和初始化一个由SpringIOC容器管理的新对象的方法,也就是说通过@Bean可以生成一个IOC容器的bean实例,类似于XML配置文件的<bean/>
可以在Spring的@Component注解的类,然后在类中使用@Bean注解任何方法(仅仅是可以),然后在方法中去创建对象,进行返回。
上一点中,通常使用的是@Configuration和@Bean配合使用。
例如:

@Configuration
public class AppConfig{

    @Bean
    public MyService myService(){
        return new MyServiceImpl();
    }
}

在AppConfig这个类上用了@Configuration,就相当于AppConfig这个类就是一个配置文件。然后里边有一个方法返回的是一个MyService类型,方法内部创建了对象并返回,这个方法用@Bean注解。这个方法用Bean注解,相当于创建了一个bean,id是myService,class对应MyServiceImpl,也就是创建了MyService接口MyServiceImpl的实现类的对象。
也就是

<beans><bean id="myService" class="com.services.MyServiceImpl"></beans>

这两段的起到的效果是一样的,都是在Spring的IOC容器中添加一个对象。不过第一种是使用编码加注解的方式,第二种是基于XML配置文件的方式。

自定义Bean name,init-method,destroy-method

@Configuration
public class AppConfig{

    @Bean(name="myFoo")
    public Foo foo(){
        return new Foo();
    }
}

这里@Bean(name=”myFoo”)指定bean的name,就相当于xml文件中写的bean的id。

同时还支持init-method和destroy-method,这个和之前说到的bean的生命周期里的初始化和销毁方法是一样的。
比如在类Foo中有init()方法,在类Bar里有destroy()方法,@Bean下的方法中return new Foo();,可以写@Bean(initMethod=”init”),另一个销毁方法同理。要注意的是,那个初始化方法和销毁方法是return中的那个,也就是new的实现类。

看个例子:
定义接口Store和实现类StringStore,里边有初始化方法和销毁方法。

public interface Store {}
public class StringStore implements Store {
    public void init() {
        System.out.println("This is init.");
    }
    public void destroy() {
        System.out.println("This is destroy.");
    }   
}

定义一个类StoreConfig并使用@Configuration来注解

@Configuration
public class StoreConfig {

    @Bean
    public Store getStringStore(){
        return new StringStore();
    }
}

在单元测试类中要想获取bean,肯定要知道bean的id是什么,是前边的store(Store首字母小写)还是stringStore(StringStore首字母小写),都不是。
如果使用@Bean这个注解,在没有指定name的时候,那么Bean的name是方法名,所以这里应该是getStringStore。不过以getStringStore作为bean的名称不太合适,所以稍微修改为stringStore。

@Configuration
public class StoreConfig {

    @Bean
    public Store stringStore(){
        return new StringStore();
    }
}

单元测试类中为

@Test
public void test() {
    Store store = super.getBean("stringStore");
    System.out.println(store.getClass().getName());
}

输出为com.imooc.beanannotation.javabased.StringStore
因为方法返回的是StringStore()。

如果指定了名称,那么getBean中的参数就不是方法名,而是指定的那个名称。
还可以指定initMethod和destroyMethod,这两个方法在实现类中,这样单元测试类中测试是会先执行initMethod,然后结束时会执行destroyMethod。

@Bean(name = "stringStore", initMethod="init", destroyMethod="destroy")
public Store stringStore() {
    return new StringStore();
}