获取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,并将相关的类进行加载。
将当前方法的返回值对象交给IOC容器进行管理。通过注解的name/value属性指定bean名称,默认为方法名。
@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