@Configuration使用场景
创始人
2024-05-30 18:52:06
0

文章目录

  • 一、简单介绍
  • 二、注解说明
    • 1. @Configuration源码
    • 2. @Configuration使用场景
  • 三、 使用案例
    • 1. 验证proxyBeanMethods属性的作用
      • 1.1 验证proxyBeanMethods取值为true的情况
        • (1)创建Person类
        • (2)创建ConfigurationAnnotationConfig类
        • (3)创建ConfigurationAnnotationTest类
        • (4)测试案例
      • 1.2 验证proxyBeanMethods取值为false的情况
        • (1)修改proxyBeanMethods属性的值
        • (2)测试案例
    • 2. 传入配置类创建IOC容器
      • (1)删除@Configuration注解
      • (2)测试案例
    • 3. 传入包名创建IOC容器
      • (1)修改测试类
      • (2)删除@Configuration注解
      • (3)测试案例
      • (4)添加@Configuration注解
      • (5)再次测试案例

一、简单介绍

  • @Configuration注解可以标注到类上,当标注到类上时,启动Spring就会自动扫描@Configuration注解标注的类,将其注册到IOC容器中,并被实例化成Bean对象。
  • 如果被@Configuration注解标注的类中存在使用@Bean注解标注的创建某个类对象的方法,那么,Spring也会自动执行使用@Bean注解标注的方法,将对应的Bean定义信息注册到IOC容器,并进行实例化。

二、注解说明

@Configuration注解是从Spring 3.0版本开始加入的一个使Spring能够支持注解驱动开发的标注型注解,主要用于标注在类上。当某个类标注了@Configuration注解时,表示这个类是Spring的一个配置类。@Configuration注解能够替代Spring的applicationContext.xml文件,并且被@Configuration注解标注的类,能够自动注册到IOC容器并进行实例化。

1. @Configuration源码

源码详见:org.springframework.context.annotation.Configuration。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {@AliasFor(annotation = Component.class)String value() default "";// Since: 5.2boolean proxyBeanMethods() default true;// Since: 6.0boolean enforceUniqueMethods() default true;
}

@Configuration注解中每个属性的含义如下所示:

  • value:存入到Spring IOC容器中的Bean的id。
  • proxyBeanMethods:从Spring 5.2版本开始加入到@Configuration注解,表示被@Configuration注解标注的配置类是否会被代理,并且在配置类中使用@Bean注解生成的Bean对象在IOC容器中是否是单例对象,取值为true或者false。当取值为true时,表示full(全局)模式,此模式下被@Configuration注解标注的配置类会被代理,在配置类中使用@Bean注解注入到IOC容器中的Bean对象是单例模式,无论调用多少次被@Bean注解标注的方法,返回的都是同一个Bean对象。当取值为false时,表示lite(轻量级)模式,此模式下被@Configuration注解标注的配置类不会被代理,在配置类中使用@Bean注解注入到IOC容器中的Bean对象不是单例模式,每次调用被@Bean注解标注的方法时,都会返回一个新的Bean对象。默认的取值为true。
  • enforceUniqueMethods:从Spring 6.0开始加入到@Configuration注解,指定使用@Bean注解标注的方法是否需要具有唯一的方法名称,取值为true或者false。当取值为true时,表示使用@Bean注解标注的方法具有唯一的方法名称,并且这些方法名称不会重叠。当取值为false时,表示使用@Bean注解标注的方法名称不唯一,存在被重叠的风险。默认取值为true。

从@Configuration注解的源码也可以看出,@Configuration注解本质上是一个@Component注解,所以,被@Configuration注解标注的配置类本身也会被注册到IOC容器中。同时,@Configuration注解也会被@ComponentScan注解扫描到。

2. @Configuration使用场景

基于Spring的注解开发应用程序时,可以将@Configuration注解标注到某个类上。当某个类被@Configuration注解标注时,说明这个类是配置类,可以在这个类中使用@Bean注解向IOC容器中注入Bean对象,也可以使用@Autowired、@Inject和@Resource等注解来注入所需的Bean对象。

注意:基于Spring的注解模式开发应用程序时,在使用AnnotationConfigApplicationContext类创建IOC容器时,需要注意如下事项:

(1)如果调用的是AnnotationConfigApplicationContext类中传入Class类型可变参数的构造方法来创建IOC容器,表示传入使用@Configuration注解标注的配置类的Class对象来创建IOC容器,则标注到配置类上的@Configuration注解可以省略。
如果传入的配置类上省略了@Configuration注解,则每次调用配置类中被@Bean注解标注的方法时,都会返回不同的Bean实例对象。

AnnotationConfigApplicationContext类中传入Class类型可变参数的构造方法源码如下所示:

public AnnotationConfigApplicationContext(Class... componentClasses) {this();register(componentClasses);refresh();
}

(2)如果调用的是AnnotationConfigApplicationContext类中传入String类型可变参数的构造方法来创建IOC容器,表示传入应用程序的包名来创建IOC容器,则标注到配置类上的@Configuration注解不能省略。
AnnotationConfigApplicationContext类中传入String类型可变参数的构造方法源码如下所示:

public AnnotationConfigApplicationContext(String... basePackages) {this();scan(basePackages);refresh();
}

三、 使用案例

1. 验证proxyBeanMethods属性的作用

proxyBeanMethods属性可取值为true或者false。取值为true时,无论调用多少次在被@Configuration注解标注的类中被@Bean注解标注的方法,返回的都是同一个Bean对象。取值为false时,每次调用在被@Configuration注解标注的类中被@Bean注解标注的方法,都回返回不同的Bean对象。

1.1 验证proxyBeanMethods取值为true的情况

(1)创建Person类

Person类主要是用来注册到IOC容器中,并实例化对象。

public class Person {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}

(2)创建ConfigurationAnnotationConfig类

ConfigurationAnnotationConfig类的作用就是充当程序启动的配置类,会在ConfigurationAnnotationConfig类上标注@Configuration注解,说明ConfigurationAnnotationConfig类是Spring启动时的配置类。

@Configuration
public class ConfigurationAnnotationConfig {@Beanpublic Person person(){return new Person();}
}

可以看到,在ConfigurationAnnotationConfig类上标注了@Configuration注解,由于@Configuration注解中的proxyBeanMethods属性默认为true,所以在ConfigurationAnnotationConfig类上的@Configuration注解省略了proxyBeanMethods属性。

(3)创建ConfigurationAnnotationTest类

ConfigurationAnnotationTest类的作用就是整个案例程序的启动类,对整个案例程序进行测试。

public class ConfigurationAnnotationTest {private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationAnnotationTest.class);public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class);ConfigurationAnnotationConfig config = context.getBean(ConfigurationAnnotationConfig.class);Person person1 = config.person();Person person2 = config.person();LOGGER.info("person1 == person2 ===>> {}", (person1 == person2));}
}

可以看到,在ConfigurationAnnotationTest类的main()方法中,首先基于AnnotationConfigApplicationContext常见了IOC容器context,从context中获取了ConfigurationAnnotationConfig类的Bean实例对象config,接下来,调用两次config的person()方法分别赋值给Person类型的局部变量person1和person2,最后打印person1是否等于person2的日志。

(4)测试案例

运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。

person1 是否等于 person2 ===>> true

通过输出的结果信息可以看出,person1是否等于person2输出的结果为true。说明当@Configuration注解中的proxyBeanMethods属性为true时,每次调用使用@Configuration注解标注的类中被@Bean注解标注的方法时,都会返回同一个Bean实例对象。

1.2 验证proxyBeanMethods取值为false的情况

验证@Configuration注解中的proxyBeanMethods属性为false的情况,与验证proxyBeanMethods属性为true的情况的案例程序基本一致,只是将ConfigurationAnnotationConfig类上标注的@Configuration注解的proxyBeanMethods属性设置为false,案例实现的具体步骤如下所示。

(1)修改proxyBeanMethods属性的值

@Configuration(proxyBeanMethods = false)
public class ConfigurationAnnotationConfig {@Beanpublic Person person(){return new Person();}
}

(2)测试案例

运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。

person1 是否等于 person2 ===>> false

从输出的结果信息可以看出,person1是否等于person2输出的结果为false。说明当@Configuration注解中的proxyBeanMethods属性为false时,每次调用使用@Configuration注解标注的类中被@Bean注解标注的方法时,都会返回不同的Bean实例对象。

2. 传入配置类创建IOC容器

调用AnnotationConfigApplicationContext类的构造方法传入配置类的Class对象创建IOC容器时,可以省略配置类上的@Configuration注解,案例的具体实现步骤如下所示。

(1)删除@Configuration注解

public class ConfigurationAnnotationConfig {@Beanpublic Person person(){return new Person();}
}

(2)测试案例

运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。

person1 是否等于 person2 ===>> false

从输出的结果信息可以看到,输出了person1是否等于person2的结果为false。说明调用AnnotationConfigApplicationContext类的构造方法传入配置类的Class对象创建IOC容器时,可以省略配置类上的@Configuration注解,此时每次调用配置类中被@Bean注解标注的方法时,都会返回不同的Bean实例对象。

3. 传入包名创建IOC容器

调用AnnotationConfigApplicationContext类的构造方法传入包名创建IOC容器时,不能省略配置类上的@Configuration注解,案例的具体实现步骤如下所示。

(1)修改测试类

修改ConfigurationAnnotationTest类的main()方法中,创建AnnotationConfigApplicationContext对象的代码,将调用传入Class对象的构造方法修改为调用传入String对象的方法,修改后的代码如下所示。

public class ConfigurationAnnotationTest {private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationAnnotationTest.class);public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lwk.demo.spring.annocation.configuration.config");ConfigurationAnnotationConfig config = context.getBean(ConfigurationAnnotationConfig.class);Person person1 = config.person();Person person2 = config.person();LOGGER.info("person1 是否等于 person2 ===>> {}", (person1 == person2));}
}

(2)删除@Configuration注解

public class ConfigurationAnnotationConfig {@Beanpublic Person person(){return new Person();}
}

(3)测试案例

运行ConfigurationAnnotationTest类的main()方法,可以看到程序抛出了异常信息,如下所示。

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'io.binghe.spring.annotation.chapter01.configuration.config.ConfigurationAnnotationConfig' available

从输出的结果信息可以看出,调用AnnotationConfigApplicationContext类的构造方法传入包名创建IOC容器时,不能省略配置类上的@Configuration注解,否则会抛出NoSuchBeanDefinitionException。

(4)添加@Configuration注解

@Configuration
public class ConfigurationAnnotationConfig {@Beanpublic Person person(){return new Person();}
}

(5)再次测试案例

再次运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。

person1 是否等于 person2 ===>> true

从输出的结果信息可以看到,输出了person1是否等于person2的结果为true,再次说明调用AnnotationConfigApplicationContext类的构造方法传入包名创建IOC容器时,不能省略配置类上的@Configuration注解。

相关内容

热门资讯

工作评语 工作评语大全  评语在工作中非常的重要,它是衡量一个人的工作是否到位的重要标准,一点都马虎不得。以下...
燃气安全知识宣传标语 燃气安全知识宣传标语精选  在日常学习、工作抑或是生活中,大家都听说过或者使用过一些比较经典的标语吧...
企业工厂大门的标语 企业工厂大门的标语大全  在日常学习、工作抑或是生活中,大家都不可避免地会接触到标语吧,标语的作用是...
数学节口号 数学节口号大全  在我们平凡的日常里,大家或多或少都接触过一些经典的口号吧,通过口号可以增加团队凝聚...
庆六一标语 庆六一标语  在平凡的学习、工作、生活中,说到标语,大家肯定都不陌生吧,标语是用简短文字写出的有宣传...
运动会方队口号 运动会方队口号(精选230句)  在学习、工作、生活中,大家对口号都再熟悉不过了吧,口号一般都用一两...
安全行车宣传标语 安全行车宣传标语大全  在平平淡淡的日常中,大家最不陌生的就是标语了吧,标语具有在理智上启发人们,在...
毕业生登记表班组鉴定评语 毕业生登记表班组鉴定评语精选  1、该同学的优点是诚实、热情、好学,性格坚毅。缺点是好胜心比较强,学...
高三冲刺励志的标语 高三冲刺励志的标语(精选240句)  在日复一日的学习、工作或生活中,许多人对一些广为流传的标语都不...
社团招新吸引人宣传语 社团招新吸引人宣传语  在日新月异的现代社会中,大家都接触过很多优秀的宣传语吧,宣传语以其时间性、阶...
最新跳蚤市场吸引人的口号 最新跳蚤市场吸引人的口号  买来的东西用过一两次,扔了又可惜。这个时候我们便可以放到跳蚤市场进行二次...
文明礼仪广告标语50则   1、让礼一寸,得礼一尺;尊重人人,人人尊重。  2、团结,诞生兴旺;勤奋,孕育成功;文明,开创未...
全国法制宣传日的宣传标语 全国法制宣传日的宣传标语(精选170句)  在学习、工作或生活中,大家都不可避免地会接触到标语吧,标...
高三励志横幅标语 高三励志横幅标语(精选235句)  无论是身处学校还是步入社会,大家都有令自己印象深刻的标语吧,标语...
5S管理的标语 关于5S管理的标语(精选240句)  在平时的学习、工作或生活中,大家或多或少都接触过一些经典的标语...
扫黑除恶的宣传标语 扫黑除恶的宣传标语(精选50句)  在生活、工作和学习中,大家一定没少看到过标语吧,标语既有公文语体...
世界宽容日宣传主题标语 世界宽容日宣传主题标语  在现实生活或工作学习中,大家总少不了接触一些耳熟能详的标语吧,标语是一种最...
儿童足球队口号 儿童足球队口号  在一片绿茵球场上,每个人都为这个球而紧张疯狂。以下是一些关于足球比赛口号,激情口号...
医院宣传标语 医院宣传标语  1、宁可自己麻烦百次,不让患者麻烦一次。  2、为患者着想,替百姓服务,白衣天使献爱...
淘宝裤子好评 淘宝裤子好评(精选100句)  在日常学习、工作抑或是生活中,大家都收藏过令自己印象深刻的句子吧,从...