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

news2024/9/30 2:44:04

目录

  • 前言
  • 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");
        };
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2-1静态库

静态库制作 编写库文件 test.c #include<stdio.h> int main(void){printf("%d\n",add(3,5));return 0; }add.c int add(int a,int b){return ab; }生成.o(目标文件) 用nm查看.o文件 T代表add这个函数的链接性是外部链接&#xff0c;即全局可见&#xff0c;…

03_Shell变量

【Shell】03_Shell变量 一、环境变量 Linux系统配置文件&#xff08;全局配置文件和用户个人配置文件&#xff09;中定义的变量&#xff0c;提供给所有Shell程序使用 1.1、全局环境变量 1.1.1、配置文件位置 /etc/environment /etc/bashrc&#xff08;或者/etc/bash.bashrc…

tensorflow张量生成以及常用函数

张量tensor&#xff1a;多维数组&#xff08;列表&#xff09; 阶&#xff1a;张量的维数 维数 阶 名字 例子 0-D 0 标量 scalar s 1&#xff0c; 2&#xff0c; 3 1-D 1 向量 vector…

Mac VSCode 突然闪退、崩溃、打不开了

1、 思路历程 VSCode 作为前端常用开发工具&#xff0c;其重要性就不一一描述了。 所以 VSCode 突然打不开了&#xff0c;真的是让我一脸懵逼。 本来以为问题不大&#xff0c;于是 &#xff1a; 1、重启了一下VSCode 2、关机重启了一下电脑&#xff1b; 3、清理了一下缓存&am…

阈值分割后配合Connection算子和箭头工具快速知道区域的ID并选择指定区域

代码 dev_close_window () read_image (Image, E:/机器视觉学习/海康视觉平台/二期VM视觉学习/二期VM视觉学习/机器视觉程序/标定相机找圆心和焊头修正相机找圆心之算法软件/标定相机找圆心和焊头修正相机找圆心之算法软件/03 标定相机找圆心/S2/1号机/1.bmp) get_image_size …

Ensp配置防火墙的web界面

Ensp配置防火墙的web界面 准备工作新建网卡配置网卡 启动防火墙配置防火墙注意事项和错误如果云里面没有网卡选项防火墙启动不了没有web界面启动不了没有web界面 准备工作 新建网卡 我用的是win10系统&#xff0c;新建网卡 先右键管理 再点击设备管理器 --- 再网络适配器 接…

【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

通用个人客户关系管理系统设计

设计一个通用个人客户关系管理系统&#xff08;Personal CRM&#xff09;&#xff0c;旨在帮助个人用户管理他们的社交网络、职业联系人、个人项目和日常沟通&#xff0c;需要关注以下几个核心设计原则和功能模块&#xff1a; 核心设计原则 易用性&#xff1a;界面简洁直观&a…

【操作系统】进程管理——信号量机制(个人笔记)

学习日期&#xff1a;2024.7.9 内容摘要&#xff1a;信号量机制&#xff0c;用信号量实现进程的同步与互斥 信号量机制 信号量的概念 在上节内容中&#xff0c;我们学习了进程互斥的软件和硬件解决方案&#xff0c;但这些方案都有各自的问题&#xff0c;双标志法都因为检查和…

机器人三定律及伦理分析

全世界的机器人定律并没有一个统一的标准或体系&#xff0c;但是在科学文献中&#xff0c;最广为人知的是由科幻小说家阿西莫夫提出的“机器人三定律”。本文将以这些定律为基础&#xff0c;分析现有的机器人伦理和实际应用中的问题&#xff0c;给出若干实例&#xff0c;并对相…

LVS集群及其它的NAT模式

1.lvs集群作用&#xff1a;是linux的内核层面实现负载均衡的软件&#xff1b;将多个后端服务器组成一个高可用、高性能的服务器的集群&#xff0c;通过负载均衡的算法将客户端的请求分发到后端的服务器上&#xff0c;通过这种方式实现高可用和负载均衡。 2.集群和分布式&#…

【光伏仿真系统】光伏设计的基本步骤

随着全球对可再生能源需求的不断增长&#xff0c;光伏发电作为一种清洁、可再生的能源形式&#xff0c;正日益受到重视。光伏设计是确保光伏系统高效、安全、经济运行的关键环节&#xff0c;它涉及从选址评估到系统安装与维护的全过程。本文将详细介绍光伏设计的基本步骤&#…

AI大模型走进汽车车机,智驾将是未来

车机里的AI大模型在汽车行业中的应用越来越广泛&#xff0c;主要体现在智能座舱和自动驾驶系统的深度融合上。通过将AI大模型应用于车机系统&#xff0c;可以实现更高智能化的人车交互体验。AI大模型作为人工智能发展的核心引擎&#xff0c;正在成为汽车智能化发展的关键之一。…

【靶机实战】GeoServer 远程代码执行漏洞复现

# 在线靶场 可以通过访问极核官方靶场开启靶机实验&#xff1a;极核靶场 -> 漏洞复现靶场 -> GeoServer-远程代码执行 原文&#xff1a;【靶机实战】GeoServer 远程代码执行漏洞复现 - 极核GetShell (get-shell.com) # 简介 CVE-2024-36401是一个高危的远程代码执行漏…

Springboot项目实训--day2

今天学习的是idea和MySQL的连接&#xff0c;以及一些基本的增删改查的功能实现。 一、软件下载 昨天下载了idea&#xff0c;今天要是西安它们的连接&#xff0c;就需要再下载MySQL&#xff0c;我的MySQL是前面几个学期别人帮忙下载的&#xff0c;所以具体的操作步骤我也不清楚…

VSTO插件功能介绍-清除空行(列)

提示目前我的插件命名为“哆哆Excel”&#xff0c;还没有打包&#xff0c;主要是自己工作中要用到的东西&#xff0c;它能提高我的工作效率&#xff0c;10倍以上开发&#xff1a;Visual Studio 2019语言&#xff1a;VB.net看个图吧 今天要记录的问题是这样子的 当时有一个同事&…

HTTP 概况

Web的应用层协议是超文本传输协议(HyperTextTransferProtocol&#xff0c;HTTP)&#xff0c;它是 Web的核心。HTTP由两个程序实现:一个客户程序和一个服务器程序。客户程序和服务器程序运行在不同的端系统中&#xff0c;通过交换HTTP报文进行会话。HTTP定义了这些报文的结构以及…

基于CentOS Stream 9平台搭建FRP内网穿透

内网穿透方法很多&#xff0c;本文以github上很火的frp为例 1.frp官方 文档&#xff1a;https://gofrp.org/zh-cn/docs/overview/ 1.1 下载 https://github.com/fatedier/frp/releases 选中合适的版本 2. 服务端&#xff08;服务器&#xff09;搭建frps 需要公网IP服务器 选…

Qt Creator仿Visual Studio黑色主题

转自本人博客&#xff1a;Qt Creator仿Visual Studio黑色主题 1.演示 配置文件和步骤在后面&#xff0c;先看成品&#xff0c;分别是QWidget和QML的代码编写界面&#xff1a; 2. 主题配置文件 下载链接&#xff1a;QtCreator _theme_VS_dark.xml 也可以自己新建一个xml文件&…

【单片机毕业设计选题24053】-基于单片机的WiFi控制门禁系统设计

系统功能: 系统上电后OLED显示智能门禁系统 Door:xxxxxx 初始化ESP8266完成后显示 Door:Closed 短按按键SW4可打开电磁锁OLED显示Door:Open&#xff0c;约五秒后电磁锁自动关闭OLED 显示Door:Closed 根据“TCP调试助手使用说明”操作&#xff0c; 在调试助手界面发送Open后…