@Configuration 和 @Bean

@Configuration 用于定义配置类,可替换 xml 配置文件,被注解的类内部包含有一个或多个被 @Bean 注解的方法,这些方法将会被AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext 类进行扫描,并用于构建 bean 定义,初始化 Spring 容器。

@Bean 是一个方法级别上的注解,主要用在 @Configuration 注解的类里,也可以用在 @Component 注解的类里。添加的bean的id为方法名。

简单使用:

@Configuration
public class ConfigDemo {
    @Bean
    public User user1(){
        User user = new User("heigou",18);
        return user;
    }
}
@SpringBootApplication
public class Demo3Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Demo3Application.class, args);
        ConfigDemo configDemo = run.getBean(ConfigDemo.class);
        User user1 = configDemo.user1();
        System.out.println(user1); //User(name=heigou, age=18)
    }
}

@Bean 默认是单例模式:

@SpringBootApplication
public class Demo3Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Demo3Application.class, args);
        ConfigDemo configDemo = run.getBean(ConfigDemo.class);
        User user1 = configDemo.user1();
        User user2 = configDemo.user1();
        System.out.println(user1 == user2); //true
    }
}

可以通过 @Configuration(proxyBeanMethods = false) 将 @Bean 方法被调用时返回的组件都是新创建的:

@Configuration(proxyBeanMethods = false)
public class ConfigDemo {
    @Bean
    public User user1(){
        User user = new User("heigou",18);
        return user;
    }
}
@SpringBootApplication
public class Demo3Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Demo3Application.class, args);
        ConfigDemo configDemo = run.getBean(ConfigDemo.class);
        User user1 = configDemo.user1();
        User user2 = configDemo.user1();
        System.out.println(user1 == user2); //false
    }
}

Spring Boot 在2.2.0版本(依赖于Spring 5.2.0)起就把它的所有的自动配置类的此属性改为了false,即 @Configuration(proxyBeanMethods = false) ,提高Spring启动速度。

  • FULL模式: @Configuration(proxyBeanMethods = true) ,保证每个@Bean方法被调用多少次返回的组件都是单实例的。配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用 FULL 模式。
  • LITE模式: @Configuration(proxyBeanMethods = false) ,每个@Bean方法被调用多少次返回的组件都是新创建的,配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断。

@Component

@Component用于标注在类上,标注了该注解的类将会被Spring扫描并注入到Spring IOC容器中。

添加了该注解的类,会在Spring启动阶段被扫描并注入到IOC中。具体流程如下:

Spring启动 -> 触发 ClassPathBeanDefinitionScannerdoScan 方法 -> 根据配置路径读取 class 的信息 -> 判断类是否包含 @Component 注解 -> 将包含注解的类根据其信息创建成 BeanDefinition -> 注册到Spring中。

@Controller, @Service, @Repository 是 @Component 的细化,这三个注解比 @Component 带有更多的语义,它们分别对应了控制层、服务层、持久层的类。

注意:@Mapper 是 mybatis 中的注解。

@ComponentScan

@ComponentScan主要就是定义扫描的路径从中找出标识了标识了@Controller,@Service,@Repository,@Component注解的类自动装配到spring的bean容器中。

如果你的其他包都在使用了 @SpringBootApplication 注解的 mainApp 所在的包及其下级包,则你什么都不用做,SpringBoot会自动帮你把其他包都扫描了。

如果你有一些bean所在的包,不在mainApp的包及其下级包,那么你需要手动加上@ComponentScan注解并指定那个bean所在的包。

@Import

给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名:

@Import({User.class, DBHelper.class})
@Configuration
public class MyConfig {
}

@Conditional

条件装配:满足Conditional指定的条件,则进行组件注入。

@ImportResource

原生配置文件引入:

======================beans.xml=========================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="haha" class="com.atguigu.boot.bean.User">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="18"></property>
    </bean>

    <bean id="hehe" class="com.atguigu.boot.bean.Pet">
        <property name="name" value="tomcat"></property>
    </bean>
</beans>
@ImportResource("classpath:beans.xml")
public class MyConfig {}

======================测试=================
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha:"+haha);//true
System.out.println("hehe:"+hehe);//true