@EnableAutoConfiguration、ApplicationContext、@Configuration注解、@Bean注解以及配置自动扫描、bean作用域

EnableAutoConfiguration

@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。

详解参加:SpringBoot之@EnableAutoConfiguration注解

ApplicationContext

先通过一个简单的例子理解下ApplicationContext的作用


public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
   }

关于主要程序有以下两个要点需要注意:

第一步是我们使用框架 API ClassPathXmlApplicationContext() 来创建应用程序的上下文。这个 API 加载 beans 的配置文件并最终基于所提供的 API,它处理创建并初始化所有的对象,即在配置文件中提到的 beans。

第二步是使用已创建的上下文的 getBean() 方法来获得所需的 bean。这个方法使用 bean 的 ID 返回一个最终可以转换为实际对象的通用对象。一旦有了对象,你就可以使用这个对象调用任何类的方法。

当SpringApplication创建,初始化了上述的 Application Context和Application Listeners

在这里插入图片描述

在spirng boot 执行到各个阶段时执行Listener事件和Context事件

所以,所谓的SpringApplicationRunListeners实际上就是在SpringApplication对象的run方法执行的不同阶段,去执行一些操作,并且这些操作是可配置的。
参考Spring Boot 运行原理,自动配置

以下内容转自:Configuration注解
javaConfig类的关键是为其添加@Configuration注解。

@Configuration注解、@Bean注解以及配置自动扫描、bean作用域

@Configuration注解表明这个类是一个配置类。可以启动组件扫描,用来将带有@Bean的实体进行实例化bean等

@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的,作用为:配置spring容器(应用上下文)

1、@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的,作用为:配置spring容器(应用上下文)

package com.test.spring.support.configuration;

@Configuration
public class TestConfiguration {
    public TestConfiguration(){
        System.out.println("spring容器启动初始化。。。");
    }
}

相当于:

<?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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false">


</beans>

主方法进行测试:

package com.test.spring.support.configuration;

public class TestMain {
    public static void main(String[] args) {

        //@Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        //如果加载spring-context.xml文件:
        //ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
    }
}

从运行主方法结果可以看出,spring容器已经启动了:

八月 11, 2016 12:04:11 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@203e25d3: startup date [Thu Aug 11 12:04:11 CST 2016]; root of context hierarchy
spring容器启动初始化。。。

2、@Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的,作用为:注册bean对象

bean类:

package com.test.spring.support.configuration;

public class TestBean {

    public void sayHello(){
        System.out.println("TestBean sayHello...");
    }

    public String toString(){
        return "username:"+this.username+",url:"+this.url+",password:"+this.password;
    }

    public void start(){
        System.out.println("TestBean 初始化。。。");
    }

    public void cleanUp(){
        System.out.println("TestBean 销毁。。。");
    }
}

配置类:

package com.test.spring.support.configuration;

@Configuration
public class TestConfiguration {
        public TestConfiguration(){
            System.out.println("spring容器启动初始化。。。");
        }

    //@Bean注解注册bean,同时可以指定初始化和销毁方法
    //@Bean(name="testNean",initMethod="start",destroyMethod="cleanUp")
    @Bean
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }
}

主方法测试类:

package com.test.spring.support.configuration;

public class TestMain {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);
        //获取bean
        TestBean tb = context.getBean("testBean");
        tb.sayHello();
    }
}

注:
(1)、@Bean注解在返回实例的方法上,如果未通过@Bean指定bean的名称,则默认与标注的方法名相同;

(2)、@Bean注解默认作用域为单例singleton作用域,可通过@Scope(“prototype”)设置为原型作用域;

(3)、既然@Bean的作用是注册bean对象,那么完全可以使用@Component、@Controller、@Service、@Ripository等注解注册bean,当然需要配置@ComponentScan注解进行自动扫描。

bean类:

package com.test.spring.support.configuration;

//添加注册bean的注解
@Component
public class TestBean {

    public void sayHello(){
        System.out.println("TestBean sayHello...");
    }

    public String toString(){
        return "username:"+this.username+",url:"+this.url+",password:"+this.password;
    }
}

配置类:

@Configuration

//添加自动扫描注解,basePackages为TestBean包路径
@ComponentScan(basePackages = "com.test.spring.support.configuration")
public class TestConfiguration {
    public TestConfiguration(){
        System.out.println("spring容器启动初始化。。。");
    }

    //取消@Bean注解注册bean的方式
    //@Bean
    //@Scope("prototype")
    //public TestBean testBean() {
    //  return new TestBean();
    //}
}

主方法测试获取bean对象:

public class TestMain {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);
        //获取bean
        TestBean tb = context.getBean("testBean");
        tb.sayHello();
    }
}

sayHello()方法都被正常调用。

### Spring框架中 `@Bean` 注解的功能与作用 #### 1. 功能概述 `@Bean` 是 Spring 框架中的一个重要注解,其主要功能是指定一个方法返回的对象应作为 Spring 容器中的 Bean 实例进行管理[^1]。这意味着当某个类的方法被标注为 `@Bean` 后,该方法的执行结果会被注册到 Spring 的 IOC(Inversion of Control)容器中,并可供其他组件依赖注入。 具体来说,`@Bean` 注解的核心目的是将普通的 Java 对象转化为 Spring 管理的 Bean,从而能够利用 Spring 提供的各种特性,比如生命周期管理、AOP 支持以及事务控制等功能[^2]。 --- #### 2. 使用场景分析 以下是 `@Bean` 注解的主要使用场景: - **手动定义复杂 Bean** 当无法通过简单的类扫描机制自动识别并注册某些复杂的对象时,可以借助 `@Bean` 手动将其注册至 Spring 容器中。例如第三方库中的类或者需要动态初始化逻辑的情况[^3]。 - **配置外部资源** 如果应用程序需要加载一些外部资源(如数据库连接池、文件流等),可以通过带有 `@Bean` 注解的方法来完成这些资源的初始化工作,并交由 Spring 统一管理。 - **替代 XML 配置** 在早期版本的 Spring 中,开发者通常会采用基于 XML 文件的方式来定义 Beans。而现代开发更倾向于使用 Java Config 方式代替冗长繁琐的 XML 编写方式,此时便需要用到 `@Bean` 来显式声明所需的 Beans[^4]。 --- #### 3. 工作原理解析 当 Spring 应用启动时,如果检测到了某 Configuration 类中标记有 `@Configuration` 内部包含若干个带 `@Bean` 注解的方法,则会对每一个这样的方法依次调用一次并将它们的结果存储起来形成最终的应用上下文环境。值得注意的是,对于同一个标记了 `@Bean` 的方法而言,在整个应用运行期间只会被执行一次,之后再请求对应类型的实例都会直接从缓存里获取而不是重新计算生成新的实例。 此外,还可以自定义设置诸如名称、作用域之类的属性给每个单独的 bean 增加灵活性。例如下面这段代码展示了如何指定 bean 名称为 "customName": ```java @Configuration public class AppConfig { @Bean(name = "customName") public MyService myService() { return new MyServiceImpl(); } } ``` --- #### 4. 测试验证示例 为了检验上述理论知识的实际效果,这里给出一段完整的单元测试案例演示如何正确运用 `@Bean` 注解: ```java // 配置@Configuration public class AppConfig { @Bean public MyBean myBean() { return new MyBeanImpl(); // 返回具体的实现类实例 } } // 主程序入口 public class SpringBeanApplicationTests { public static void main(String[] args) { // 创建基于注解ApplicationContext ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取名为 'myBean' 的 Bean 并打印出来确认无误 Object beanInstance = context.getBean("myBean"); System.out.println(beanInstance instanceof MyBean); // 输出 true 表明成功获得目标类型 } } ``` 此例子清晰地展现了从定义到实际使用的全过程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值