原文 https://www.cnblogs.com/cxuanBlog/p/11179439.html
1.源码
/* * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.context.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.core.annotation.AliasFor; @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Bean { @AliasFor("name") String[] value() default {}; @AliasFor("value") String[] name() default {}; @Deprecated Autowire autowire() default Autowire.NO; String initMethod() default ""; String destroyMethod() default AbstractBeanDefinition.INFER_METHOD; }
2.@Bean 基础声明
Spring的@Bean注解用于告诉方法。会产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
SpringIOC 容器管理一个或者多个bean,这些bean都需要在@Configuration注解下进行创建。
基础使用实例
1)配置类
@Configuration //表示是个配置类 public class AppConfig { // 使用@Bean 注解表明myBean需要交给Spring进行管理 // 未指定bean 的名称,默认采用的bean的名称是 "方法名" 且 "方法名首字母小写" @Bean public MyBean myBean(){ return new MyBean(); } }
2)实例pojo类
public class MyBean { public MyBean(){ System.out.println("MyBean Initializing"); } }
3)使用@bean创建的对象
1.通过上下文对象获取(AnnotationConfigApplicationContext注释配置应用上下文)
ApplicationContext context = new AnnotationConfigApplicationContext(DruidConfig.class); Object bean = context.getBean("myBean");
2.@Autowired注入
@Autowired private MyBean myBean;
3.@Bean 构成
3.1注解说明
1)@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
表示不仅可以作用在方法上,也可以作用在注解类型上
2)@Retention(RetentionPolicy.RUNTIME)
表示在运行时提供注册。
3)@Documented
表明@Bean注解应该被 javadoc工具记录
3.2属性说明
1)value: name属性的别名,在只需要写一个name属性的时候,可以name=写成value=
2)name: 此bean 的名称,或多个名称。如果未指定,则bean的名称是带注解方法的名称(首字母小写)。
3)autowire : 此注解的方法表示自动装配的类型,返回一个Autowire类型的枚举,我们来看一下Autowire枚举类型的概念
autowire 枚举确定自动装配状态:即,bean是否应该使用setter注入由Spring容器自动注入其依赖项。// 这是Spring DI的核心概念
public enum Autowire { // 常量,表示根本没有自动装配。 NO(AutowireCapableBeanFactory.AUTOWIRE_NO), // 常量,通过名称进行自动装配 BY_NAME(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME), // 常量,通过类型进行自动装配 BY_TYPE(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); private final int value; Autowire(int value) { this.value = value; } public int value() { return this.value; } public boolean isAutowire() { return (this == BY_NAME || this == BY_TYPE); } }
@Bean的autowire的默认值为No,默认表示不通过自动装配。
4)initMethod: @Bean注释的方法创建的对象的类里面的初始化方法名
5)destroyMethod: @Bean注释的方法创建的对象的类里面的销毁方法名
6)initMethod和destroyMethod使用实例
实例类
public class MyBean { public MyBean(){ System.out.println("MyBean Initializing"); } public void init(){ System.out.println("Bean 初始化方法被调用"); } public void destroy(){ System.out.println("Bean 销毁方法被调用"); } }
配置类
@Configurationpublic class AppConfig { // @Bean @Bean(initMethod = "init", destroyMethod = "destroy") public MyBean myBean(){ return new MyBean(); } }
初始化方法在得到Bean的实例的时候就会被调用,销毁方法在容器销毁或者容器关闭的时候会被调用。
4.@Bean注释的方法带参数时-参数名字问题
@Bean(name = "dynamicDataSource") public DynamicDataSource dataSource(DataSource masterDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); return new DynamicDataSource(masterDataSource, targetDataSources); }
如上,有参数masterDataSource。
如果spring容器中只有一个DataSource 类型的bean,那么这里参数的名字可以随意取,spring的这个DataSource 的bean会作为参数传入
如果spring容器有多个DataSource 类型的bean
那么参数的名字一定要对应bean的名称,这样子才能把这个bean作为参数传入,否则报错。
或者使用来制定DataSource 的名字