spring常见注解
@Bean注解详解:
1.常见问题思考:
问题1:为啥下面我们明明使用了@Bean 注解但是在spring容器中却找不到该catDemo啊?
1 | public class config { |
原因:单独一个@Bean修饰的 只是一个bean的定义,并没有注册到spring容器中!spring中要使用@Bean修饰 的bean需要将该bean注册到spring容器中!可以使用@Componet 注解 或者该注解修饰的注解将该类注册到容器中的同时连带注册@Bean 修饰的bean .
解决方法:
1 | 1.在类上加入@Componet注解或者是@Componet注解修饰的注解,把该类注入到spring容器,然后由spring |
理解:
SpringBoot - @Bean注解详解_springboot @bean注解-CSDN博客
1.@Bean注解就是把我们将要实例化的对象转化成一个Bean,放在Spring容器中,等我们使用时,就会和@Autowired、@Resource配合到使用拿到该实例。注册BEAN的方法有@ComponentScan、@Bean、@Import、@Component、@Repository、@ Controller、@Service 、 @Configration等等。
2.@Bean 注解:作用在方法上,声明当前方法的返回值是一个Bean对象;单独只有这个注解修饰的方法,只是实现了对bean的一种定义,其类没有注册到spring容器中,那么该方法返回的bean也没有注册到spring容器中!
3.注解@Bean被声明在方法上,该方法都需要有一个返回类型,这个方法的返回类型就是注册到IOC容器中的类型,接口和类都是可以作为返回类型,介于面向接口原则,提倡返回类型为接口。该注解主要用在@Configuration注解的类的方法上,也可以用在@Component注解的类的方法上,添加的bean的id为方法名。
4.使用要点
(1)@Bean 注解:作用在方法上,方法都需要有一个返回类型;
(2)@Bean 注解:用于表示当前方法返回一个 Spring 容器管理的 Bean;
(3)@Bean 的默认的名字和方法名一致(一般Bean都是首字母小写,因为方法名的首字母一般都是小写的);
(4)@Bean 注解:一般和 @Component 或者 @Configuration 一起使用;
(5)@Bean 注解:默认作用域为单例作用域,可通过 @Scope(“prototype”) 设置为原型作用域;
(6)@Bean 注解:可以接受一个 String 数组来设置多个别名;
(7)@Configration 注解类中可以声明多个 @Bean 的方法,并且声明的 Bean 与 Bean 之间是可以有依赖关系的;
5.组合使用
@Bean 注解常常与 @Scope、@Lazy,@DependsOn 和 @link Primary 注解一起使用:
(1)@Profile 注解:为不同环境下不同的配置提供了支持,如开发和生产环境的数配置是不同的;
(2)@Scope 注解:将 Bean 的作用域从单例改变为指定的作用域;
(3)@Lazy 注解:只有在默认单例作用域的情况下才有实际效果;
(4)@DependsOn 注解:表示在当前 Bean 创建之前需要先创建特定的其他 Bean的场景时,添加该注解。
测试:
1 |
|
@Configuration:
【Spring注解必知必会】深度解析@Configuration注解 - 掘金
注解源码:
一般修饰在类上!
1 |
|
属性说明:
- value: 自定义当前组件或者说bean的名称,实际就是@Component的value属性。
- proxyBeanMethods: 判断是否bean的方法应该被代理,默认是true,后面原理解析中重点分析。
元注解说明:
- 该注解只能使用在类,接口、枚举、其他注解上
- 该注解的生命周期是运行时JVM
- @Component元注解,相当于拥有了@Component注解的能力,可以被ComponentScan扫描到,变成spring中的Bean。
proxyBeanMethods()属性:
1.proxyBeanMethods属性默认为true,当其值为false时,将不会进行代理处理,并且每次调用@Bean注解标注的方法时都会创建一个新的Bean实例。
@Component注解:
说明:
用来标记的类是一个“组件”或者说是一个Bean,Spring会自动扫描标记;注解的类作为一个Spring Bean对象。;该注解只能使用在类,接口,枚举,和其他注解上!
注解源码:
1 |
|
属性说明:
value:自定义当前组件或者说bean的名称!如果不配置,默认为组件的首字母小写的类名!
@Scope:
【Spring注解必知必会】全面了解@Scope - 掘金
源码:
1 |
|
注解有3个属性,value和scopeName一样,用来表示注解的作用于范围。proxyMode用来为spring bean设置代理。
作用域(value或者scopeName)属性范围
- singleton: 默认值,单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。
- prototype: 原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。
- request: 对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效。
- session: 对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效。
默认的作用域范围为singleton。
proxyMethod属性:
- DEFAULT:proxyMode的默认值,一般情况下等同于NO,即不需要动态代理。
- NO:不需要动态代理,即返回的是Bean的实例对象。
- INTERFACES:代理的对象是一个接口,即@Scope的作用对象是接口,这种情况是基于jdk实现的动态代理。
- TARGET_CLASS:代理的对象是一个类,即@Scope的作用对象是一个类,上面例子中的ClassB就可以用这种代理,是以生成目标类扩展的方式创建代理,基于CGLib实现动态代理。
后面通过实例来讲解下我们为什么要有这个属性。
使用注解:
前面讲了该注解作用在类上或者方法上,但是其实它前提必须是一个Bean,所以存在下面两种情况:
作用在类上
搭配@Component、@Service注解
1 |
|
作用在方法上
搭配@Bean注解使用
1 |
|
通常我们不配置Scope情况下的Bean的作用域都是单例模式singleton,不进行任何代理。
实例演示:
我们前面讲解了通过Bean如何控制我们Bean的作用域范围,那我们通过例子演示验证下。
1 | public class PrototypeBean { |
1 |
|
验证代码:
1 | PrototypeBean prototypeBean1 = context.getBean(PrototypeBean.class); |
执行结果:
1 | 实例化 PrototypeBean |
小结:
- prototype多例模式,每次在调用getBean() 获取实例时,都会重新实例化,初始化。
- prototype多例模式,它的Bean实例对象则不受IOC容器的管理,最终由GC来销毁。
- ingleton单实例模式下,多次getBean()取到的对象是一样的。
- 针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法。
@ConfigurationProperties:
@ConfigurationProperties注解的作用是什么?
将标注了@ConfigurationProperties注解的Spring容器中的Bean与配置文件中的属性进行一一绑定,用于更加快速、方便的读取配置文件的内容。
也就是:先将属性对象注册到Spring容器中,再进行属性的绑定。(正是因为该特性,即使在方法走set了某些属性,其也会被配置文件中的属性覆盖)
@ConfigurationProperties注解可以搭配使用的注解有哪些?
只要能够将属性对象注册到Spring容器中的注解都可以搭配使用。
@RestController、@Service、@Repository、@Component、@Configuration、@Bean都可以和@ConfigurationProperties注解搭配使用。
@ConfigurationProperties注解如何使用?:
1 | 1.需要将配置对象类注入到Spring容器中,一般使用 进行注入,当然 、 、 都属于 ,因为他们有更准确的意义,所以一般使用 ;或者不使用组件类,而是在启动类上使用 ,将配置对象类注入到Spring容器中;或者在定义Bean的时候将配置信息和配置对象的属性进行一一绑定。 |
①. 使用@Component + @ConfigurationProperties(prefix = “spring.drools”),这两个注解都标注在配置对象上。
1 | DroolsProperties.java如下: |
②. @EnableConfigurationProperties(DroolsProperties.class) + @ConfigurationProperties(prefix = “spring.drools”) ,注意:配置对象上的注解只有@ConfigurationProperties,@EnableConfigurationProperties标注在启动类上。
1 |
|
1 | MySpringApplication.java如下: |
③. @Bean + @ConfigurationProperties(prefix = “spring.drools”),配置类上没有注解,在定义Bean时将将配置信息和配置对象的属性进行一一绑定。
1 |
|
1 |
|
@EnableConfigurationProperties:
@EnableConfigurationProperties注解的作用是什么?
将标注了@ConfigurationProperties注解的类注入到Spring容器中。该注解是用来开启对@ConfigurationProperties注解的支持。也就是@EnableConfigurationProperties注解告诉Spring容器能支持@ConfigurationProperties注解。
@EnableConfigurationProperties注解如何使用?
一般情况下会定义两个文件,一个用于绑定application.xml中的配置信息,一个用于定义配置类。一般情况下@EnableConfigurationProperties搭配@Configuration和@SpringBootApplication使用!
①. 定义一个属性类用于绑定配置信息:
1 |
|
②. 定义一个配置类用于开启文件属性的绑定功能:
1 | // 配置类 |
@Import 注解:
spring注解之@Import注解的三种使用方式 - 掘金
@Import注解须知:
1、@Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中
2、加入IOC容器的方式有很多种,@Import注解就相对很牛皮了,@Import注解可以用于导入第三方包 ,当然@Bean注解也可以,但是@Import注解快速导入的方式更加便捷
3、@Import注解有三种用法
该注解主要是将第三方包注入IOC容器中!@Import 注入的容器明明都有相关注解了为什么还需要额外的@Import 的注解了?
那是因为spring启动类能扫描到的注范围有限!使用该注解可以让spring启动类扫描到第三方包里面的相关注解!
简单示例分析:
@Import的三种用法:
1、直接填class数组方式 2、ImportSelector方式【重点】 3、ImportBeanDefinitionRegistrar方式
第一种用法:直接填class数组:
直接填对应的class数组,class数组可以有0到多个。
1 |
|
对应的import的bean都将加入到spring容器中,这些在容器中bean名称是该类的全类名
第二种用法:ImportSelector方式
这种方式的前提就是一个类要实现ImportSelector接口,假如我要用这种方法,目标对象是Myclass这个类,分析具体如下:
1 | public class Myclass implements ImportSelector { |
分析实现接口的selectImports方法中的:
- 1、返回值: 就是我们实际上要导入到容器中的组件全类名【重点 】
- 2、参数: AnnotationMetadata表示当前被@Import注解给标注的所有注解信息【不是重点】
需要注意的是selectImports方法可以返回空数组但是不能返回null,否则会报空指针异常!
1 | public class Myclass implements ImportSelector { |
1 |
|
1 | /** |
第三种用法:ImportBeanDefinitionRegistrar方式:
这种用法比较自定义化注册:
1 | public class Myclass2 implements ImportBeanDefinitionRegistrar { |
参数分析:
- 第一个参数:annotationMetadata 和之前的ImportSelector参数一样都是表示当前被@Import注解给标注的所有注解信息
- 第二个参数表示用于注册定义一个bean
1 | public class Myclass2 implements ImportBeanDefinitionRegistrar { |
1 |
|
@ConditionalOnMissingBean:
对比说明:
@ConditionalOnBean有则注入;@ConditionalOnMissBean没有则注入;@Conditional条件满足则注入。
1 | 注解只作用在 定义的方法上 |
@Autowired:
@Autowired是一种注解,可以对构造器、方法、参数、字段和注解进行标注,源码如下:
1 |
|
(1). @Autowired一般用在Controller层中用来装配Service对象,当同一个Service接口对象有多个实现时,需要使用@Qualifier来制定具体的装载依赖,否则会报错,除非用@Autowired标注的属性/方法的类型是Map或者List:No qualifying bean of type ‘com.hadoopx.file.service.ISysFileService’ available: expected single matching bean but found 2: LocalSysFileServiceImpl,FastDfsSysFileServiceImpl,当然这个问题也可以使用@Primary来解决。
NoUniqueBeanDefinitionException,说明有多个满足条件的bean进行自动装配,程序无法正确做出判断使用哪一个,通过将@Qualifier注解与我们想要使用的特定Spring bean的名称一起进行装配,Spring框架就能从多个相同类型并满足装配要求的bean中找到我们想要的
(2). @Autowired根据类型进行自动装配,如果需要按名称进行装配,则需要配合@Qualifier使用。
(3). @Autowired在装配依赖对象时,默认要求依赖对象必须存在,如果允许为NULL,需要设置required属性为false。
(4). 被@Autowired标注的属性/方法所在的类,需要是Spring容器中的bean。
(5). 被@Autowired标注的属性/方法的类型是Map且Key为String类型,Spring则会把所有符合该类型的bean装载到Map中,key是bean名称,value则为该bean的实例。在简单工程模式中,可以使用该特性替换传统的将服务实现存入Map的方式。
(6). 被@Autowired标注的属性/方法的类型是List,Spring则会把所有符合该类型的bean装载到List集合中。
(7). @Autowired与@Resource都可以用来装配bean,都可以写在字段上。@Autowired默认按类型装配,@Resource(这个注解属于J2EE的),默认安照名称进行装配,名称可以通过name属性进行指定。