聊聊分布式架构07-[Spring]IoC和AOP

news2025/1/13 7:44:24

目录

Spring IoC

IoC的设计与实现

简单容器BeanFactory

高级容器ApplicationContext

IoC容器工作过程

Spring AOP

简单的Spring AOP示例


Spring IoC

IoC(Inversion of Control): IoC是一种设计原则,它反转了传统的控制流。

  • 在传统的编程中,应用程序通常负责控制对象的创建和生命周期。

  • 而在IoC中,控制权被反转,应用程序不再负责直接创建和管理对象,而是将这些职责委托给一个容器或框架。这个容器负责实例化、组装和管理对象,使得应用程序的组件更加解耦、可维护和可扩展。

IoC的设计与实现

Spring Ioc容器的设计中,可以看到两个主要的容器系列:简单容器BeanFactory和高级容器ApplicationContext。

简单容器BeanFactory

简单模拟下BeadFactory演示IoC的设计:

  1. 创建配置文件,包含BeanDefinition的信息。

    user:com.elaine.myspring.ioc.beanfactory.bean.User
  2. 创建一个BeanDefinition类,定义bean的属性。

    public class BeanDefinition {
        private String beanName;
    ​
        private Class beanClass;
    ​
        public String getBeanName() {
            return beanName;
        }
    ​
        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }
    ​
        public Class getBeanClass() {
            return beanClass;
        }
    ​
        public void setBeanClass(Class beanClass) {
            this.beanClass = beanClass;
        }
    }
  3. 创建资源加载器ResourceLoader,用来加载配置文件中的配置。

    /**
     * 载入配置文件,通过BeanDefinition解析加载
     */
    public class ResourceLoader {
        public static Map<String, BeanDefinition> getResource() {
            Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(16);
            Properties properties = new Properties();
            try {
                InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");
                properties.load(inputStream);
                // 迭代遍历配置文件
                Iterator<String> iterator = properties.stringPropertyNames().iterator();
                while (iterator.hasNext()) {
                    String key = iterator.next();
                    String className = properties.getProperty(key);
                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setBeanName(key);
                    Class clazz = Class.forName(className);
                    beanDefinition.setBeanClass(clazz);
                    // 加载资源
                    beanDefinitionMap.put(key, beanDefinition);
                }
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return beanDefinitionMap;
        }
    }
    ​
  4. 创建对象注册器BeanRegister,注册bean到container中。

    public class BeanRegister {
        // 假设所有对象都是单例的,用一个单例map缓存
        private Map<String, Object> singletonMap = new HashMap<>();
    ​
        /**
         * 获取单例bean
         * @param beanName
         * @return
         */
        public Object getSingletonBean(String beanName) {
            return singletonMap.get(beanName);
        }
    ​
        /**
         * 注册单例bean
         * @param beanName
         * @param bean
         */
        public void registerSingletonBean(String beanName, Object bean) {
            if(singletonMap.containsKey(beanName)) {
                return;
            }
            singletonMap.put(beanName, bean);
        }
    }
  5. 创建对象工厂BeanFactory,初始化需要完成资源的加载,对象注册器的创建。

    public class BeanFactory {
        private BeanRegister beanRegister;
    ​
        private Map<String, BeanDefinition> map = new HashMap<>();
    ​
        public BeanFactory(){
            // 创建bean注册器
            beanRegister = new BeanRegister();
            // 加载资源
            this.map = new ResourceLoader().getResource();
        }
    ​
        /**
         * 获取bean
         * @param beanName
         * @return
         */
        public Object getBean(String beanName) {
            Object bean = beanRegister.getSingletonBean(beanName);
            if (bean != null) {
                return bean;
            }
            return createBean(map.get(beanName));
        }
    ​
        /**
         * 创建bean
         * @param beanDefinition
         * @return
         */
        private Object createBean(BeanDefinition beanDefinition) {
            try {
                Object bean = beanDefinition.getBeanClass().newInstance();
                beanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);
                return bean;
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
  6. 测试验证。

    public class TestUser {
        @Test
        public void beanFactory() {
            BeanFactory beanFactory = new BeanFactory();
    ​
            // 第一次获取,通过反射
            User user = (User) beanFactory.getBean("user");
            user.sayHello();
    ​
            // 第二次获取,通过缓存
            User user1 = (User) beanFactory.getBean("user");
            user.sayHello();
    ​
            // 所有对象都是单例的前提下,是同一个对象
            System.out.println(user1 == user);
        }
    }
高级容器ApplicationContext
  • ApplicationContext继承自BeanFactory,拥有更多的功能和特性,包括国际化、事件传播、资源访问等。

  • 和BeanFactory的延迟加载不同,ApplicationContext会在容器启动时就实例化和初始化所有的bean。

  • 支持更丰富的配置方式,包括XML配置、注解、java配置等,并且支持自动扫描并注册bean。

ApplicationContext通过读取xml配置的形式获取bean:

public class MySpringApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Product product = (Product) applicationContext.getBean("product");
        System.out.println(product.getId());
    }
}
IoC容器工作过程

Spring 的 IOC 容器⼯作的过程,其实可以划分为两个阶段:容器启动阶段和Bean实例化阶段。

Spring AOP

AOP是Aspect-Oriented Programming(面向方面编程或面向切面)的简称,是一种编程范式,用于增强、扩展和管理应用程序的功能。

  • 通过将交叉关注点(Cross-Cutting Concerns)从应用程序的主要业务逻辑中分离出来,实现了更好的模块化和可维护性。

  • 通常包括日志记录、事务管理、安全性、异常处理等方面的功能。

简单的Spring AOP示例

1.项目中添加Spring AOP相关的依赖。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>5.3.27</version>
        </dependency>

2.创建一个目标类(Target Class),这是我们将应用AOP的类。

public class MyService {
    public void showTime() {
        System.out.println("Now :" + new Date(System.currentTimeMillis()));
    }
​
    public void sayHi() {
        System.out.println("Hi");
    }
}

3.创建一个切面类(Aspect Class),这是我们的AOP切面。

@Aspect
public class LoggerAspect {
    public final static Logger logger = LoggerFactory.getLogger(LoggerAspect.class);
​
    /**
     * MyService类作为切点
     */
    @Pointcut("execution(* com.elaine.myspring.aop.service.MyService.*(..))")
    public void myLogger(){}
​
​
    @Before("myLogger()")
    public void doBefore() {
        logger.info("Before PointCut, say Hello!");
    }
​
    @After("myLogger()")
    public void doAfter() {
        logger.info("After PointCut, say Bye!");
    }
}

4.配置文件配置AOP

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置目标对象 -->
    <bean id="myService" class="com.elaine.myspring.aop.service.MyService" />
    <!-- 配置切面 -->
    <bean id="loggingAspect" class="com.elaine.myspring.aop.aspect.LoggerAspect" />
    <!-- 启用AOP自动代理 -->
    <aop:aspectj-autoproxy/>
</beans>

5.调用方法

public class MySpringApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        MyService service = (MyService) applicationContext.getBean("myService");
        service.showTime();
        service.sayHi();
    }
}

结果

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

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

相关文章

mysql select语句中from 之后跟查询语句

概念&#xff1a;将from后面的查询语句放在FROM的后面&#xff0c;则查询到的结果&#xff0c;就会被当成一个“表”; 这里有一个特别要注意的地方&#xff0c;放在FROM后面的子查询&#xff0c;必须要加别名。 select dui.id,dui.party_service_id mes_id, dui.party_id,dui.…

精彩回顾|【ACDU 中国行·成都站】数据库主题交流活动成功举办!

2023年10月14日下午&#xff0c;【ACDU 中国行成都站】在成都市武侯区星宸假日酒店圆满落下帷幕。本次活动由中国数据库联盟&#xff08;ACDU&#xff09;联合墨天轮社区主办&#xff0c;围绕「数据库技术及应用」这一主题&#xff0c;六位数据库资深专家从数据库性能管理、数据…

Spring framework Day20:Spring AOP xml配置示例三

前言 本章节我们继续学习 AspectJ&#xff01; AspectJ是一个基于Java语言的面向切面编程(AOP)的扩展框架&#xff0c;它的诞生解决了很多传统面向对象编程的问题。在传统的面向对象编程中&#xff0c;开发者通常会将一些通用功能或者横切关注点&#xff08;cross-cutting co…

开发者基于 chroot 打造的工具macOS Containers

导读macOS Containers 是一群开发者基于 chroot 打造的工具&#xff0c;能让你在 macOS 用 Docker 运行 macOS 镜像。 macOS Containers 官网写道&#xff1a; 容器从根本上改变了现代软件的开发和部署方式。包括 FreeBSD、Solaris、Linux 甚至 Windows 在内的多种操作系统都支…

RabbitMQ的五种常见消费模型

目录 引言1. 简单队列模型&#xff08;Simple Queue Model&#xff09;优缺点及适用场景代码示例 2. 工作队列模型&#xff08;Work Queue Model&#xff09;优缺点及适用场景代码示例 3. 发布/订阅模型&#xff08;Publish/Subscribe Model&#xff09;优缺点及适用场景代码示…

论文解析-moETM-多组学整合模型

论文解析-moETM 参考亮点动机发展现状现存问题 功能方法Encoder改进Decoder改进 评价指标生物保守性批次效应移除 实验设置结果多组学数据整合cell-topic mixture可解释性组学翻译性能评估RNA转录本、表面蛋白、染色质可及域调控关系研究1. 验证同一主题下&#xff0c;top gene…

Android12之DRM基本接口实现(二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Android性能优化系列-腾讯matrix-流量监控之TrafficPlugin源码分析

前言 本篇进行matrix框架的网络流量监控模块的代码分析。你可能想&#xff0c;为什么需要对流量进行监控呢&#xff1f;我们平常进行的网络接口请求都是一些必要的操作&#xff0c;监控它的意义何在&#xff1f;首先我们要明确流量监控的对象是什么&#xff0c;是上行&#xf…

【学习笔记】RabbitMQ-5 消息的可靠性投递 以及示例代码

参考资料 RabbitMQ官方网站RabbitMQ官方文档噼咔噼咔-动力节点教程 文章目录 八、RabbitMQ的确认机制 -confirm8.1 Confirm 模式简介8.2 具体代码设置8.2.1 **设置思路**&#xff1a;8.2.2 **代码实现**8.2.2.1 开启生产者的确认模式.8.2.2.2 实现接口ComfirmCallback8.2.2.3 配…

Transformer模型 | Transformer模型描述

谷歌推出的BERT模型在11项NLP任务中夺得SOTA结果,引爆了整个NLP界。而BERT取得成功的一个关键因素是Transformer的强大作用。谷歌的Transformer模型最早是用于机器翻译任务,当时达到了SOTA效果。Transformer改进了RNN最被人诟病的训练慢的缺点,利用self-attention机制实现快…

浪涌防护:TSS管的工作原理与应用?|深圳比创达EMC

浪涌防护&#xff1a;TSS管的工作原理与应用&#xff1f;相信不少人是有疑问的&#xff0c;今天深圳市比创达电子科技有限公司就跟大家解答一下&#xff01; 一、TSS工作原理 TSS半导体放电管是一种电压开关型瞬态抑制二极管&#xff0c;即涌压抑制晶体管&#xff0c;或称为导…

大中小企业自招人力及劳务派遣招聘

抖音直播招聘报白是一种通过直播方式展示职位信息并与求职者互动的招聘方式。在抖音平台上&#xff0c;企业或人力资源公司可利用直播将职位以视频直播的方式展现&#xff0c;这种方式可给求职者带来更强的代入感和真实性&#xff0c;解决其对岗位真假难辨的信任问题。 图片 …

SCB-Dataset3 公开 学生课堂行为数据集: A Benchmark for Detecting Student Classroom Behavior

公开 学生课堂行为数据集 SCB-Dataset 2 Student Classroom Behavior dataset b站&#xff1a;https://www.bilibili.com/video/BV1D34y1g76E/ arxiv: https://arxiv.org/pdf/2310.02522.pdf github: https://github.com/Whiffe/SCB-dataset 百度云&#xff1a;https://pan…

如何选择适合的发电机测试设备?

选择适合的发电机测试设备需要考虑电机的额定功率和负载需求&#xff0c;选择能够满足需求的测试设备&#xff0c;确保测试设备的功率范围覆盖发电机的额定功率&#xff0c;并有一定的余量。常见的发电机测试项目包括电压、电流、频率、功率因数、转速、温度等参数的测试&#…

PCB布线时如何保证100M以上信号的稳定性?

PCB布线时是电子工程中非常重要的环节&#xff0c;对于保证信号的稳定性和完整性至关重要&#xff0c;若电子工程师遇上100M以上信号的布线需求&#xff0c;该如何设计来保证其稳定性&#xff1f;下面或许能给你些参考。 1、选择合适的传输介质 对高速信号&#xff0c;选择合适…

基于 SaaS 搭建的党建小程序源码系统 带完整的搭建教程

随着互联网技术的发展和应用的普及&#xff0c;传统的党建模式已经难以满足现代社会的需求。为了更好地服务党员和群众&#xff0c;提高党组织的凝聚力和战斗力&#xff0c;基于 SaaS搭建的党建小程序源码系统应运而生。小程序的出现可以很好的解决大多数问题&#xff0c;方便了…

数字孪生与智慧城市:重塑未来城市生活的奇迹

今天&#xff0c;我们将探讨数字孪生和智慧城市两个颠覆性技术&#xff0c;它们正引领着未来城市生活的巨大变革。随着科技的飞速发展&#xff0c;数字孪生和智慧城市成为实现可持续发展和提升居民生活质量的关键策略。 数字孪生&#xff1a;实现现实与虚拟的完美融合 数字孪生…

AI工具在工作中的“大作用”

现如今科技的发展让我们的生活越来越便利&#xff0c;一些AI工具的出现&#xff0c;更对我们的工作有莫大的帮助。 AI工具的辅助就像给上班族提供了一种更加高级的“摸鱼方法”&#xff0c;大大提高了打工人的工作效率。如果有一种什么都能回答你&#xff0c;甚至能帮助你完成…

用例图包含关系、扩展关系、泛化关系解析(最全总结,非常详细)

一、用例图中的各种关系 a&#xff09;参与者与用例间的关联关系&#xff1a;参与者与用例之间的通信&#xff0c;也成为关联或通信关系。 b&#xff09;用例与用例之间的关系&#xff1a;包含关系&#xff08;include&#xff09;、扩展关系&#xff08;extend&#xff09;、…

智慧机场航线监测系统:提升航空运输安全与效率的新一步

在当今世界&#xff0c;空中出行已经成为越来越多人生活的一部分。人们频繁地乘坐飞机来往各地&#xff0c;全球航空旅行需求不断增长&#xff0c;航空运输业已经变得越来越复杂。在这个复杂性不断增强的行业中&#xff0c;智慧机场应用航线监测系统成为了航空领域关键的发展趋…