详细分析Spring中的@Configuration注解基本知识(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. 详细分析
  • 3. Demo
    • 3.1 简单Bean配置
    • 3.2 属性配置
    • 3.3 多条件配置
  • 4. 实战拓展

前言

Java的基本知识推荐阅读:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. Spring框架从入门到学精(全)

拓展应用补充阅读:@Configuration注解使用

1. 基本知识

在Java和Spring框架中,@Configuration注解用于定义配置类,这些类可以替代传统的XML配置文件

  • 是Spring的一部分,用于创建和管理bean,提供了更灵活和强大的配置机制
  • 配置类包含了一个或多个@Bean方法,这些方法返回要在Spring容器中管理的bean

基本示例如下:

AppConfig类被标注为一个配置类,并且定义了一个myService方法,该方法返回一个MyService实例

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

自动装配:
配置类中的bean可以自动装配到其他bean中

@Configuration
public class AnotherConfig {

    private final MyService myService;

    @Autowired
    public AnotherConfig(MyService myService) {
        this.myService = myService;
    }

    @Bean
    public AnotherService anotherService() {
        return new AnotherServiceImpl(myService);
    }
}

2. 详细分析

注解继承与组合:
@Configuration类可以使用其他Spring注解,如@ComponentScan和@Import,来扫描组件或导入其他配置类

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // Bean定义
}

@Configuration
@Import(AppConfig.class)
public class MainConfig {
    // 主要配置
}

代理机制:
@Configuration类在Spring容器启动时会通过CGLIB动态代理机制生成代理类,以确保@Bean方法只被调用一次,从而保证单例bean的行为

@Configuration
public class ConfigClass {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }

    @Bean
    public AnotherBean anotherBean() {
        // myBean() 方法将返回相同的实例,而不会创建新实例
        return new AnotherBean(myBean());
    }
}

条件化配置:
使用@Conditional注解,可以根据某些条件来决定是否创建某个bean

@Configuration
public class ConditionalConfig {

    @Bean
    @Conditional(MyCondition.class)
    public MyBean conditionalBean() {
        return new MyBean();
    }
}

环境和属性配置:
使用@PropertySource和@Value注解可以将外部属性文件中的值注入到配置类中

@Configuration
@PropertySource("classpath:application.properties")
public class PropertyConfig {

    @Value("${my.property}")
    private String myProperty;

    @Bean
    public PropertyBean propertyBean() {
        return new PropertyBean(myProperty);
    }
}

3. Demo

3.1 简单Bean配置

总体完整的Demo如下:

// AppConfig.java
package com.example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyService();
    }

    @Bean
    public MyController myController() {
        return new MyController(myService());
    }
}

// MyService.java
package com.example.demo;

public class MyService {
    public String sayHello() {
        return "Hello, World!";
    }
}

// MyController.java
package com.example.demo;

public class MyController {
    private final MyService myService;

    public MyController(MyService myService) {
        this.myService = myService;
    }

    public String greet() {
        return myService.sayHello();
    }
}

// AppTest.java
package com.example.demo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MyController controller = context.getBean(MyController.class);
        System.out.println(controller.greet());  // 输出: Hello, World!
    }
}

最终执行结果如下:

在这里插入图片描述

3.2 属性配置

// AppConfig.java
package com.example.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {

    @Value("${app.message}")
    private String message;

    @Bean
    public MessageService messageService() {
        return new MessageService(message);
    }
}

// MessageService.java
package com.example.demo;

public class MessageService {
    private final String message;

    public MessageService(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

// AppTest.java
package com.example.demo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MessageService service = context.getBean(MessageService.class);
        System.out.println(service.getMessage());  // 输出配置文件中的app.message值
    }
}

// application.properties
app.message=Hello from properties!

截图如下:

在这里插入图片描述

3.3 多条件配置

// AppConfig.java
package com.example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    @Conditional(MyCondition.class)
    public ConditionalService conditionalService() {
        return new ConditionalService();
    }
}

// MyCondition.java
package com.example.demo;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 返回true时才会创建ConditionalService bean
        return true;
    }
}

// ConditionalService.java
package com.example.demo;

public class ConditionalService {
    public String getMessage() {
        return "Conditional Service is active!";
    }
}

// AppTest.java
package com.example.demo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        if (context.containsBean("conditionalService")) {
            ConditionalService service = context.getBean(ConditionalService.class);
            System.out.println(service.getMessage());  // 输出: Conditional Service is active!
        } else {
            System.out.println("Conditional Service is not active");
        }
    }
}

截图如下:

在这里插入图片描述

4. 实战拓展

对于这个@Configuration注解,往往会配合proxyBeanMethods一起使用

  • proxyBeanMethods = true(默认行为):表示Spring会为配置类生成一个CGLIB代理对象,以确保每个@Bean方法只会被调用一次,并且返回相同的实例(单例模式)
    这种方式可以确保@Bean方法间的依赖能够正确处理
  • proxyBeanMethods = false:表示Spring不会为配置类生成代理对象,每次调用@Bean方法时都会返回一个新的实例
    这种方式可以减少CGLIB代理的开销,适用于@Bean方法之间没有依赖关系的场景

Demo如下:

@Configuration(proxyBeanMethods = false) 是一个Spring的注解,用于标识一个类是配置类,同时指定该配置类中@Bean方法的代理行为
方法每次调用都会返回一个新的 DeptDataPermissionRuleCustomizer 实例

@Configuration(proxyBeanMethods = false)
public class DataPermissionConfiguration {

    @Bean
    public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() {
        return rule -> {
            // dept
            rule.addDeptColumn(AdminUserDO.class);
            rule.addDeptColumn(DeptDO.class, "id");
            rule.addDeptColumn(AppointmentCommissionDO.class, "dept_id");
            // user
            rule.addUserColumn(AdminUserDO.class, "id");
            rule.addUserColumn(AppointmentCommissionDO.class, "user_id");
        };
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/788885.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

k8s集群如kubeadm init和kube-flannel.yam问题

查看k8s中角色内容kubectl get all (显示pod和server以及delment) 删除应用资源选择删除先删除部署查看部署和pod没了服务还在,但资源和功能以及删除,删除服务kubectl delete 服务名(部署名),get pods 获取默认空间的容…

毛细管计算软件

思科普毛细管计算软件 输入部分: 一是制冷剂的选取,含常用制冷剂R134A R600A R407C等 A输入热负荷 B蒸发温度 C冷凝温度 D回气温度 毛细管的选项,根据不同内径对应不同长度的毛细管

详细分析@FunctionalInterface的基本知识(附Demo)

目录 前言1. 基本知识2. Demo 前言 Java的基本知识推荐阅读: java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)Spring框架从入门到学精(全) 1. 基本知识 FunctionalInterface 是 Java 8 引入的一个注…

apache:the requested operation has failed使用httpd -t

Apache24\bin cmd 回车 httpd -t 因为我重新压缩了,记住,重新压缩要使用原路径, 因为你安装的 时候使用的是原路径 还是不行就改个端口,切记修改配置文件httpd.conf先把Tomcat停了 Define SRVROOT "F:\Apache\Apache24&q…

从生物学到机械:人眼如何为机器人视觉系统提供无尽灵感?

人眼激发了相机机制的发展,该机制改善了机器人对周围世界的观察和反应方式。 该摄像头系统由马里兰大学(UMD)计算机科学家领导的团队开发,模仿人眼用于保持清晰稳定的视力的不自主运动。 该团队对相机的原型设计和测试称为…

警惕!焦虑过度的这些症状正在悄悄侵蚀你的生活!

在快节奏的现代社会中,焦虑已成为许多人生活的一部分。适度的焦虑可以激发我们的斗志,推动我们前进。然而,当焦虑过度时,它可能会变成一把双刃剑,对我们的身心健康造成严重威胁。本文将探讨焦虑过度的表现,…

机器视觉/自然语言/生成式人工智能综合应用实验平台-实训平台-教学平台

AIGC是人工智能1.0时代进入2.0时代的重要标志,MIT 科技评论也将Al合成数据列为2022年十大突破性技术之一,甚至将生成性Al(Generative Al) 称为是AI领域过去十年最具前景的进展。同时,AIGC领域岗位需求数量暴涨。高校方面在人工智能专业与机器…

文献笔记|综述|When Large Language Model Meets Optimization

When Large Language Model Meets Optimization 题目:当大型语言模型遇到优化时 作者:Sen Huang , Kaixiang Yang , Sheng Qi and Rui Wang 来源:arXiv 单位:华南理工大学 文章目录 When Large Language Model Meets Optimization…

【android 9】【input】【10.发送按键事件4——View的分发流程】

系列文章目录 可跳转到下面链接查看下表所有内容https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501文章浏览阅读2次。系列文章大全https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501 目录…

AGE 可比性、相等性、可排序性和等效性

AGE已经对原始类型(布尔值、字符串、整数和浮点数)和映射的相等性有了良好的语义。此外,Cypher对整数、浮点数和字符串的可比性和可排序性也有很好的语义。然而,处理不同类型的值与Postgres定义的逻辑和openCypher规范存在偏差&am…

websockt初始化,创建一个webSocket示例

写文思路: 以下主要从几个方面着手写websocket相关,包括以下:什么是webSocket,webSocket的优点和劣势,webSocket工作原理,webSocket握手示例,如何使用webSocket(使用webSocket的一个示例)&#…

【安全设备】堡垒机

一、什么是堡垒机 安全运维审计与风险控制系统即堡垒机,前身为跳板机,跳板机是一个简单的管理设备,但缺乏对运维操作的控制和审计能力。堡垒机是一种特定的网络安全设备,用于在一个网络环境中保护数据和网络不受外部和内部用户的…

k8s record 20240708

一、PaaS 云平台 web界面 资源利用查看 Rancher 5台 CPU 4核 Mem 4g 100g的机器 映射的目录是指docker重启后,数据还在 Rancher可以创建集群也可以托管已有集群 先docker 部署 Rancher,然后通过 Rancher 部署 k8s 想使用 kubectl 还要yum install 安…

深度分析:智算中心建设 - GPU选型

大模型加持AI技术赛道革新发展,“大模型热”愈演愈烈。2024年2月15日,OpenAI首个视频生成模型Sora发布,完美继承DALLE 3的画质和遵循指令能力,能生成长达1分钟全尺寸的高清视频。2024年5月14日,OpenAI发布GPT-4o&#…

comsol达西定律的小例子

comsol达西定律的小例子

clean code-代码整洁之道 阅读笔记(第十七章 终章)

大纲 第十七章 味道与启发 17.1 注释 C1:不恰当的信息 C2:废弃的注释 C3:冗余注释 C4:糟糕的注释 C5:注释掉的代码 17.2 环境 E1:需要多步才能实现的构建 E2:需要多步才能做到的测试 …

computed传参

目录 一、问题 二、解决方法 三、总结 tiips:如嫌繁琐,直接移步总结即可! 一、问题 computed可以依据其他变量动态计算出值,但是v-for渲染html时,需要根据html中 传入的不同变量,来分别做处理或者利用 html中的值该…

node+vue的仿网易云音乐网站-计算机毕业设计源码02905

摘要 本论文基于Node.js和Vue.js技术,以仿网易云音乐网站为目标,设计并实现了一个具有音乐播放、歌曲搜索、歌单推荐等功能的音乐网站。首先,论文介绍了网易云音乐网站的特点和功能,分析了其前端和后端技术栈,为后续设…

CTFShow的36D杯

神光 还是想了一下,但那个异或搞不出来,都是对dword_41A038操作,想起开头就给了 key ,还有反调试应该是要调试的 输出的应该就是 flag ,只是为什么是乱码呢? 放 od 再试试,直接就出 flag 了&am…

Docker搭建kafka+zookeeper以及Springboot集成kafka快速入门

参考文章 【Docker安装部署KafkaZookeeper详细教程】_linux arm docker安装kafka-CSDN博客 Docker搭建kafkazookeeper 打开我们的docker的镜像源配置 vim /etc/docker/daemon.json 配置 { "registry-mirrors": ["https://widlhm9p.mirror.aliyuncs.com"…