spring @Bean注解
spring的@Bean注解用于告诉方法,产生一个bean对象,然后交给spring管理
基本使用
@Configuration
public class MyConfig {
/**
* bean的名称默认是方法的名称
* 也可以使用@Bean的name和value属性进行设置
* @return
*/
@Bean
//@Bean("bean1")
public MyBean myBean(){
return new MyBean();
}
}
注:@Bean其实并不一定要在@Configuration注解中,我会在之后进行说明
属性详解
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};
@AliasFor("value")
String[] name() default {};
/** @deprecated */
@Deprecated
Autowire autowire() default Autowire.NO;
boolean autowireCandidate() default true;
String initMethod() default "";
String destroyMethod() default "(inferred)";
}
属性名 | 作用 |
---|---|
value | 和name互为别名,为当前bean指定一个名称,可以设置多个 |
name | 和value互为别名,为当前bean指定一个名称,可以设置多个 |
autowire | 表示自动装配的类型,接收一个Autowire枚举, 默认NO表示没有自动装配 BY_NAME表示通过名称自动装配 BY_TYPE表示通过类型自动装配 |
autowireCandidate | 容器在进行自动装配时是否考虑此对象,默认考虑 |
initMethod | 指定初始化时调用的方法 |
destroyMethod | 指定销毁时调用的方法 |
相关注解
@Configuration
上面说到@Bean并不一定需要@Configuration内使用,其实在其它如@Component标签中使用也是可以的,但和在@Configuration中有一定的差异
full模式和lite模式
- lite模式:在没有标注@Configuration的类里有@Bean方法就称为lite模式
- 在该模式下容器里的bean是它本身,不会被cglib增强
- 由于cglib是创建子类代理,而它不进行cglib增强,故@Bean方法可以是private、final修饰的
- 该模式下不能通过方法调用来获取依赖
- 由于不进行cglib,故运行性能略高,降低了启动时间
- full模式:在有标注@Configuration的类里有@Bean方法就称为full模式
- 在该模式下配置类会被cglib增强,放入容器的是它的代理
- 由于cglib是创建子类代理,故@Bean方法 不能是private、final修改的,因为子类拿不到
- 该模式下可以通过方法调用来获取依赖
- 由于通过了cglib增强,故对新手的友好型更好
注:也可以通过@Configuration中的proxyBeanMethods属性设置lite模式还是full模式,默认full
@Profile
可以根据当前环境,动态的激活和切换一系列组件的功能
设置环境
spring环境下可以通过context.getEnvironment().setActiveProfiles("xxx");修改环境变量
springboot中可以通过spring.profiles.active=xxx指定运行环境
使用范围
@Configuration或其它类级别bean注解修饰的类上
@Bean方法上
环境可以设置多个,也可以使用
!
占位符
@Scope
设置bean的作用域
属性 | 作用 |
---|---|
singeton | 默认值,单例的,在项目启动时创建并加载到容器 |
prototype | 多例的,在获取bean时创建 |
request | bean对象的生命周期是一次http请求 |
session | bean对象的生命周期是一次http会话 |
application | bean对象的生命周期在servletContext生命周期内 |
websocket | bean对象的生命周期在webSocket生命周期内 |
globalsession | 类似于session,但只在portlet的web应用中生效 |
注:requst、session、application、websocket不能用于普通项目,只能在web项目中生效
proxyMode
该属性决定了被注解的类是否会被代理,值是一个枚举
ScopedProxyMode:
值 | 作用 |
---|---|
DEFAULT | 不是代理目标的bean |
NO | 不是代理目标的bean |
INTRFACES | 使用jdk动态代理 |
TARGET_CLASS | 使用cglib动态代理 |
@Lazy
表示一个bean是否是懒加载(延迟加载)的
- 可以作用于方法上,表示这个方法被延迟加载
- 可以作用在被@Component或其子注解注释的类上,表示这个类中所有的bean都被延迟加载
- 如果没有注释@Lazy或属性设置为false,那么该bean不会被懒加载
- 还可以作用在@Autowired和@Inject注解的属性上,这种情况下,他将为该字段创建一个惰性代理
@DependsOn
指定当前bean所依赖的bean,任何被依赖的bean都能保证在当前bean之前创建,可以控制bean的加载顺序
@Description
对bean添加描述
有时候需要提供一个详细的bean描述文本是非常有用的
当对bean暴露进行监控时,非常有用
@Conditional
根据某个条件创建特点的bean,通过实现condition接口,并重写matches接口来构建判断条件
扩展注解
注解 | 创建bean的时机 |
---|---|
@ConditionalOnBean | 在当前上下文中存在某个bean时 |
@ConditionalOnClass | 某个class位于类路径上时 |
@ConditionalOnExpression | 当表达式为true时 |
@ConditionalOnMissingBean | 当前上下文中不存在某个bean时 |
@ConditionalOnMissingClass | 某个class不存在于类路径上时 |
@ConditionalOnNotWebApplication | 不是web应用 |
@ConditionalOnWebApplication | 是web应用 |
@ConditionalOnProperty | 当指定属性有指定值时 |
@ConditionalOnJava | 当jvm为指定版本时 |
@ConditionalOnResource | 当类路径下有指定资源时 |
@ConditionalOnJndi | 在jndi存在条件下时 |
@ConditionalOnSingleCandidate | 指定bean在容器中只有一个,或有多个但指定了首选 |
@Primary
当有多个bean符合依赖注入时,最优先考虑的bean
可以和@Bean或@Component一起使用
@Import
@Import通过快速导入的方式实现把实例加入spring的ioc容器中
@Import的三种用法
-
直接填class数组
//通过这种方式添加的bean bean名是全类名 @Import({MyBean.class}) public class MyImport { }
-
ImportSelector方式
//通过这种方式添加的bean bean名是全类名 @Import({MyBean.class, MySelector.class}) public class MyImport { }
public class MySelector implements ImportSelector { /** * 实现接口中的方法 * @param annotationMetadata 表示当前被@Import注解给标注的所有注解信息 * @return 实际要导入到容器中的组件全类名,可返回空数组,但不可用直接返回null */ @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.dqn.beanann.beananndemo.pojo.MyDemo"}; } }
-
ImportBeanDefinitionRegistrar方式
//这种方式可以指定bean的名称 @Import({MyBean.class, MySelector.class, MyRegistran.class}) public class MyImport { }
public class MyRegistran implements ImportBeanDefinitionRegistrar { /** * * @param importingClassMetadata 和importSelector的参数一样表示当前被@Import注解给标注的所有注解信息 * @param registry 可用于注册bean */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class); registry.registerBeanDefinition("my",beanDefinition); } }
@ImportResource
用来导入传统的xml配置文件