【spring-boot】spring向IOC容器中注⼊bean相关知识⼀、springboot向IOC容器中注⼊bean的⼏种⽅式
案例类
public class ClockService {
public void showTime() {
System.out.println("today is "+ new Date());
}
}
View Code
第⼀种⽅式:待注⼊bean的类添加@Service或者@Component等注解
springboot会扫描启动类所在的包下⾯所有带有这些注解的类,实例化bean加到ioc容器。
@Service
public class ClockService {
public void showTime() {
System.out.println("today is "+ new Date());
}
}
View Code
第⼆种⽅式:使⽤@Configuration和@Bean注解来配置bean到ioc容器
@Configuration
public class BeanConfig {
@Bean
public ClockService clockService() {
return new ClockService();
}
}
View Code
第三种⽅式:使⽤@Import注解
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@Import(ClockService.class)
public class AutoConfDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AutoConfDemoApplication.class, args);
}
}
View Code
第四种⽅式:springboot⾃动装配机制
1、待⾃动注⼊的bean对象
package com.spring.sxf.stbean;
/**
*
*/
public class AutoConfigBean {
private String name="888888";
private String aget="999999";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAget() {
return aget;
}
public void setAget(String aget) {
this.aget = aget;
}
}
View Code
2、在该类所在jar包的resources⽬录下新建META-INF/spring.factories⽂件,⽂件内容
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.spring.sxf.stbean.AutoConfigBean
View Code
3、启动项⽬,验证容器中是否存在指定的bean
@Slf4j
@Controller
@RequestMapping("/blog")
public class BlogController implements ApplicationContextAware {
@Value("${vDesc}")
private String envDesc;
private ApplicationContext applicationContext;
@Autowired
private BlogService blogService;
@RequestMapping("/env")
@ResponseBody
public String testEnv() {
log.info("current envDesc:{}", envDesc);
boolean ainsBean("com.spring.sxf.stbean.AutoConfigBean");
if(!autoFlag){
autoFlag= ainsBean("AutoConfigBean");
}else {
AutoConfigBean Bean(AutoConfigBean.class);
log.info("spring context hasAutoConfigBean name:{},age:{}",Name(),Aget());
}
return envDesc;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
}
⽇志打印结果:[19:44:39:245] [INFO] [qtp892237946-33] - com.spring.sxf.stEnv(BlogController.java:70) - spring context hasAutoConfigBean name:888888,age:999999 View Code
⼆、springboot的spring-boot-starter-xxx的实现原理
1、原理概述:
该类starter的jar包(jar包中⽆任何代码实现)存在在项⽬中,其l⽂件会向项⽬中⾃动导⼊其他需要⾃动装配的jar包,从⽽完成springboot的⾃动装配需求。(依赖springboot的⾃动装配机制)
第⼀种情况:导⼊的jar包中的l⽂件存在传递依赖,会引⼊其他jar包,该jar包中存在⼀些@Configuration注解的配置。
第⼆种情况:导⼊的jar包的class⽬录下存在/META-INF/spring.factories⽂件,该⽂件下存在以下⾃动装配的类。
2、注解在⾃动装配的类上的注解
@ConditionalOnBean(仅仅在当前上下⽂中存在某个对象时,才会实例化⼀个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化⼀个Bean)
@ConditionalOnMissingBean(仅仅在当前上下⽂中不存在某个对象时,才会实例化⼀个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化⼀个Bean)
@ConditionalOnNotWebApplication(不是web应⽤)
@ConditionalOnClass(当注解在⽅法上,某个class位于类路径上,才会实例化⼀个Bean)
@ConditionalOnClass (当注解于类上, 某个class位于类路径上,否则不解析该注解修饰的配置类)
View Code
3、案例类
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      /licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.jdbc;
import javax.sql.DataSource;
import javax.sql.XADataSource;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.dition.AnyNestedCondition;
import org.springframework.dition.ConditionMessage;
import org.springframework.dition.ConditionOutcome;
import org.springframework.dition.ConditionalOnClass;
import org.springframework.dition.ConditionalOnMissingBean;
import org.springframework.dition.ConditionalOnProperty;
import org.springframework.dition.SpringBootCondition;
import org.springframework.boot.adata.DataSourcePoolMetadataProvidersConfiguration; import org.t.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import t.annotation.Condition;
import t.annotation.ConditionContext;
import t.annotation.Conditional;
import t.annotation.Configuration;
import t.annotation.Import;
import ype.AnnotatedTypeMetadata;
import org.springframework.bedded.EmbeddedDatabaseType;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link DataSource}.
*
* @author Dave Syer
* @author Phillip Webb
* @author Stephane Nicoll
* @author Kazuki Shimizu
* @since 1.0.0
*/
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class }) public class DataSourceAutoConfiguration {
@Configuration
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
@Configuration
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
/**
* {@link AnyNestedCondition} that checks that either {@code pe}
* is set or {@link PooledDataSourceAvailableCondition} applies.
*/
static class PooledDataSourceCondition extends AnyNestedCondition {
PooledDataSourceCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
static class ExplicitType {
}
@Conditional(PooledDataSourceAvailableCondition.class)
static class PooledDataSourceAvailable {
}
}
/
**
* {@link Condition} to test if a supported connection pool is available.
*/
static class PooledDataSourceAvailableCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {            ConditionMessage.Builder message = ConditionMessage.forCondition("PooledDataSource");
if (getDataSourceClassLoader(context) != null) {
return ConditionOutcome.match(message.foundExactly("supported DataSource"));
}
Match(message.didNotFind("supported DataSource").atAll());
}
/**
* Returns the class loader for the {@link DataSource} class. Used to ensure that
* the driver class can actually be loaded by the data source.
* @param context the condition context
* @return the class loader
*/
private ClassLoader getDataSourceClassLoader(ConditionContext context) {
Class<?> dataSourceClass = DataSourceBuilder.ClassLoader());
return (dataSourceClass != null) ? ClassLoader() : null;
}
}
/**
* {@link Condition} to detect when an embedded {@link DataSource} type can be used.
* If a pooled {@link DataSource} is available, it will always be preferred to an
* {@code EmbeddedDatabase}.
*/
static class EmbeddedDatabaseCondition extends SpringBootCondition {
private final SpringBootCondition pooledCondition = new PooledDataSourceCondition();
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {            ConditionMessage.Builder message = ConditionMessage.forCondition("EmbeddedDataSource");
if (anyMatches(context, metadata, this.pooledCondition)) {
Match(message.foundExactly("supported pooled data source"));
}
EmbeddedDatabaseType type = (ClassLoader()).getType();spring ioc注解
if (type == null) {
Match(message.didNotFind("embedded database").atAll());
}
return ConditionOutcome.match(message.found("embedded database").items(type));
}
}
}
View Code