Java Web-SpringBoot bean的管理和自动配置原理

获取bean

默认情况下,Spring项目启动时,会把bean都创建好放在IOC容器中,如果想要主动获取这些bean,可以通过如下三种方式:

1.根据name获取bean:

Object getBean (String name)

2.根据类型获取bean:

<T> T getBean (Class<T> requiredType)

3.根据name获取bean(带类型转换):

<T> T getBean (String name, Class<T> requiredType)
@Autowired
private ApplicationContest applicationContext;

public void GetBean(){

TestBean bean1=(TestBean)applicationContext.getBean("testBean");

TestBean bean2=applicationContext.getBean("TestBean.class");

TestBean bean3=applicationContext.getBean("testBean",TestBean.class);
}

bean的作用域 

Spring支持五种作用域,后三种在web环境中才生效

可以通过@Scopy注解加在bean类上来设置bean的作用域

默认bean是在容器启动时候就实例化,放入IOC容器当中。可以在bean上加上注解@Lazy注解来第一次使用时候来实例化。

第三方bean

当我们导入第三方依赖时,想把它交给IOC容器管理,我们会发现他是仅读的,这时候我们无法在bean上加上component注解来交给IOC容器管理,就要用到@Bean注解

1.在启动类中定义一个方法,方法的返回值就是我们要的bean对象。(不建议)

@SpringBootApplication
public class SpringbootWebConfig2Application {
//将方法返回值交给IOC容器管理,成为IOC容器的bean对象
@Bean
public SAXReader saxReader(){
return new SAXReader();

}

可以通过bean注解的name或者value属性来指定名称,未指定默认是方法名。

2.通过@Configuration声明一个配置类,在配置类中对bean进行集中管理,spring容器在启动的时候会去扫描@Configuration,并将相关的类进行加载。

@Configuration
public class CommonConfig {
//声明bean对象
@Bean
public SAXReader saxReader(){
return new SAXReader();

}

第三方bean想要进行依赖注入,直接在方法中指定形参即可。

@Configuration
public class CommonConfig {
//声明bean对象
@Bean
public SAXReader saxReader(Service service){
service.方法;
return new SAXReader();

}

SpringBoot自动配置

配置javaBean被扫描方法

声明bean的四大注解,想要生效,还需要被组件扫描注解@ComponentScan扫描。

@componentScan注解已经包含在了启动类注解@SpringBootApplication中。默认扫描的范围是启动类及其子包。

方案一:@ComponentScan组件扫描

@ComponentScan({"com.example","com.test"})//扫描的包名
@SpringBootApplication
public class SpringbootWebConfig2Application {

方案二:使用@Import导入。可以

1.导入普通类

@Improt(JavaBean.class)
@SpringBootApplication
public class SpringbootWebConfig2Application {
}

2.导入配置类

//配置类
@Configuration
class ConfigTest
{
@Bean
public HeadTest(){
return new headTest();
}

//导入配置类
}
@Improt(ConfigTest.class)
@SpringBootApplication
public class SpringbootWebConfig2Application {
}

3.导入ImportSerlect接口的实现类。接口中有一个selectImorts方法,返回值封装的是类名,返回值是一个字符串数组,封装的就是全类名

接口:

public class MyImportSelector implements ImportSelector {
public String[] selectImports (AnnotationMetadata importingClassMetadata) {
return new String[]{"com.example.ConfigTest"};

配置类: 

@Configuration
class ConfigTest
{
@Bean
public HeadTest(){
return new headTest();
}

导入接口实现类:

@Improt(MyImportSelect.class)
@SpringBootApplication
public class SpringbootWebConfig2Application {
}

注意:第三方可以使用注解来对Import注解到进行封装,达到简化的目的。

SpringBoot的自动配置

根据上面的JavaBean扫描方法,我们大概可以猜出SpringBoot自动配置是通过把要加载的类名集中放在文件中,再通过Import注解去扫描所有要被加载的类,接下来我们跟踪源码来查看。

首先对启动类的注解进行跟踪

我们发现最上面三个是元注解

第三个@ComponentScan注解是用来进行组件扫描的

我们继续跟进@SpingBootConfiguration

 可以看到里面有@Configration注解,这就是可以在启动类直接声明第三方Bean的原因

@Indexed注解是用来加速的,我们不用管他

返回之后来跟进@EnableAutoConfiguration注解

可以看到里面封装了Import注解,看来就是在这里导入了JavaBean,我们继续跟进Import里面的类看看它导入了什么类来把JavaBean放入IOC中

这个自动配置类实现了一个DeffredImportSelector接口

我们发现DefferredImportSelect接口实现了ImportSelect接口,相当于AutoConfigurationImportSelect类实现了ImportSelect接口。那我们就来看看这个类实现的

selectImports方法,看看把哪些JavaBean进行了加载

可以看到返回值是返回了autoConfigurationEntry的信息,而这个方法是调用了getAutoConfigurationEntry方法,我们跟进这个方法。

里面返回值是new了一个AutoConfigurationEntry对象,可以看到里面参数是要configuratios这个对象,他是一个List集合,通过调用getCandidateConfiguration方法获得,我们跟进

发现有一个断言,他说SpringBoot会自动加载配置文件中的信息。我们来找找这个文件

我们发现了,文件当中配置了很多的自动配置类当代码执行时候就会把这些Bean加载进来。这就是自动配置的原理了

我们发现了,SpringBoot中有一个配置文件当中配置了很多的自动配置类,当代码执行时候就会把这些Bean加载进来。但是配置类中有那么多类,难道他是把所有的配置类都加载进IOC中?当然不是,可以使用注解来进行按条件装配,下面介绍一下

条件装配Conditional

作用:按照一定的条件进行判断

位置:方法、类

@Conditional本身是一个父注解,派生出大量的子注解,我们主要介绍以下三个

@ConditionalOnClass:判断环境中是否有对应字节码文件,才注册bean到IOC容器。

可以通过name或value属性来指定全类名。下面的例子中,会判断当前环境是否存在JWS类,也就是我们是否在pom文件中引入了该依赖如果存在将该bean加入到IOC容器中。

@bean
@ConditionalOnClass(name="io.jsonwebtoken.JWTS")
public HeaderParser headerParser(){
return new HeaderParser();
}

@ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器。这个注解通常用于设置一个默认的bean

@ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

@bean
@ConditionalOnProperty(name="name",havingValue="ZXT")
public HeaderParser headerParser(){
return new HeaderParser();
}

yml配置文件:

name: ZXT

 

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值