基于注解的方式注册bean

方式一: 使用@Configuration和@Bean结合

图片发自App

被@Configuration注解标识的类自动获得@Component的特性,因为该注解本身也是使用了@Component注解,具体可以查看@Configuration的源码定义,并且该类会作为spring的一个配置类,在创建该类型的bean时,spring会扫描当中所有@Bean注解标注的方法,并自动执行,返回值自动注册在容器中,默认使用方法名作为bean的name。也可以通过提供@Bean的value值或设置bean的name属性来给bean起名字。

方式二:使用@ComponentScan注解自动注册

图片发自App

和在xml中配置是类似的,通过在@Component或者相关注解(比如@Controller、@Configuration、@Service都是)标注的类上使用@ComponentScan注解,spring会根据指定的扫描包路径进行扫描,自动创建所有标有@Component相关注解的类的实例,并将其注册到spring容器中,如果是@Configuration标注的,还会执行其中的@Bean方法。

我们还可以对扫描的类进行过滤,比如扫描排除包含@Controller的类:

图片发自App

上面的配置等同于xml配置:

图片发自App

比如只扫描包含@Service注解的类:

图片发自App

上面的配置等同于xml配置:

图片发自App

配置include的同时还需要指定useDefaultFilters为false,这样spring就不会自动注册包下所有的Component。

备注: @ComponentScan可以重复使用在同一个类上,用于实现多个扫描,但是这个特性需要使用jdk8及以上版本的jdk,如果使用的jdk版本低于jdk8,可以使用@ComponentScans来实现多个扫描。

我们还可以对扫描的规则进行自定义,通过指定include或者exclude的type值为CUSTOM,指定处理规则的TypeFilter类,我们需要自定义一个实现TypeFilter接口的类,并重写match方法:

图片发自App

说明:通过match方法的参数metadataReader可以获取正在扫描的类的元信息,比如类名,类上的注解信息等,match方法返回值如果是true,则是匹配。返回true的情况下,如果是include,则是注册,如果是exclude则是忽略。返回false则反之。

方式三: 使用@Import注解导入某个类注册到spring容器中

图片发自App

通过在配置类上标注@Import注解,可以快速创建某个类的实例,并导入到spring容器中。

方式三扩展一: @Import 使用ImportSelector 批量导入:

具体方法是指定@Import的值为一个实现了ImportSelector接口的类,该类重写selectImports方法,selectImports方法返回值为一个String数组,这个数组包含要导入的全限定类名。使用了ImportSelector不会将ImportSelector实现类导入,只会将selectImports方法返回的数组指定的类导入。

图片发自App

方式三扩展二:@Import 使用ImportBeanDefinitionRegistrar

自定义一个ImportBeanDefinitionRegistrar类,实现ImportBeanDefinitionRegistrar接口,重写registerBeanDefinitions方法,通过参数registry可以注册bean,比如:

图片发自App

同样是使用@Import注解将ImportBeanDefinitionRegistrar导入,同样是只会将registerBeanDefinitions方法中注册的bean注册,不会将ImportDefinitionRegistrar这个类注册进来。

方式四:使用FactoryBean(工厂Bean)注册bean

实现FactoryBean接口,实现以下三个方法:

图片发自App

示例:

图片发自App

spring判断@Bean注解的方法的返回值是一个工厂Bean,会执行工厂bean的getObject方法获得一个实例,并注册到容器中,如果是单例,则只注册一次。而不是将FactoryBean的实现类注册进来。如果想要获得工厂bean本身这个实例,可以在获取bean的时候指定的bean name前加上“&”前缀,如context.getBean("&bean")

设置bean的作用域--注解配置方式

bean的作用域有:

singleton : 单例,整个应用中只存在一个实例bean

prototype : 与单例相对,每次getBean都会重新生成一个Bean。

request : web环境下,每个请求都会创建一个bean,在一次请求中只存在一个Bean,不同request的bean不同

session : web环境下,session生命周期下,获取的是同一个bean

默认情况下是singleton单实例,可以通过以下方式来指定Bean的作用域。

图片发自App

bean 懒加载 --注解配置方式

默认情况下,所有单实例bean都会在创建spring容器的时候创建,如果在bean第一次使用的时候创建,我们称为懒加载

配置很简单,在创建bean的方法上添加@Lazy注解即可

图片发自App

按照条件注册Bean

我们可以通过某些条件,来选择是否注册Bean,通过@Condition注解来实现。

图片发自App

@Conditional注解可以添加在方法上也可以添加在类上,放在类上是对类中所有@Bean方法统一设置。

Profile 的使用

日常开发中,我们可能需要根据不同的环境来注册一套不同的Bean,比如:我们生产环境、测试环境、开发环境会使用不同的数据源。通过Profile配置,就可以指定该Bean是在某个Profile被激活时才会注册到spring容器中,这与maven中的profile是一个道理。

如下:

图片发自App

通过指定环境变量,或者jvm启动参数:-Dspring.profiles.active=dev都可以来激活profile,也可以在代码中激活profile,如:

图片发自App

@Profile注解同样可以写在配置类上,整个配置类的所有配置会在指定profile下才激活。

转载请注明出处

作者:Coder_Ring

原文链接:https://www.jianshu.com/p/bdca18850673

你可能感兴趣的:(基于注解的方式注册bean)