• 大白话讲解IOC和AOP


    IOC和AOP

    什么是IOC

    IoC(Inversion of control)控制反转,它是一种思想,而Spring Framework实现了这一思想。Ioc也称为依赖注入(DI)。

    IOC控制反转,即将new 对象的权利交给Spring容器。

    将创建对象的控制权交给Spring容器有什么好处呢?

    想象这样一个场景,我们要创建一个对象,这个对象可能依赖一个或多个其他对象,就像我们创建下面这个对象的样子。

    @Controller
    public class TestService {
        @Autowired
        private TestOneDao testOneDao;
        @Autowired
        private TestTwoDao testTwoDao;
    }
    

    我们要知道,我们依赖的对象,也可能会依赖其他的对象。这是一个嵌套的过程。要是这些依赖关系都由我们来管理,想想都崩溃吧。所以索性让Spring容器来管理这些依赖关系,也就是自动帮我们注入这些依赖。这样子我们要使用某一个对象的时候,直接向IoC容器拿就可以了。

    所以现在就比较好理解控制反转

    控制:指对象创建的权利

    反转:将控制权交给IOC容器

    IoC容器和工厂模式有什么关系呢?

    IoC中最基本的技术就是“反射”编程,通俗的讲就是根据给出的类名(字符串形式)来动态地生成对象

    我们可以把IoC容器看做是一个工厂,我们需要什么对象,直接向工厂拿就行了,一般的工产模式只能生产某一类商品,但是IoC容器它能生产不同类型的商品,之所以能做到这一点,是因为它比一般工厂模式多使用了反射机制。

    还记得我们刚学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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="..." class="...">  (1) (2)
            <!-- collaborators and configuration for this bean go here -->
        </bean>
    
        <bean id="..." class="...">
            <!-- collaborators and configuration for this bean go here -->
        </bean>
    
        <!-- more bean definitions go here -->
    
    </beans>
    

    这个全限定类名(class后面跟着的)就是反射生产对象所需的。

    什么是AOP?

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。(百度百科)

    上面的不是很好理解,举一个有关事务的例子。

    大家学习Spring的时候,可能会接触过编程式事务管理声明式事务管理

    编程式事务管理:简单的理解就是自己编写事务逻辑

    声明式事务管理:一个注解就搞定了,底层就是通过AOP实现的。

    虽然声明式事务管理是通过AOP来实现的,但是想要理解AOP的原理,还得从编程式事务管理开始。

    伪代码如下(把我们的业务代码包裹在事务中)

    事务开始
    	业务代码
    事务提交
    

    真正代码

    @Autowired
    private TransactionTemplate transactionTemplate;
    public void test() {
    
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
    
                    try {
    
                        // ....  业务代码
                    } catch (Exception e){
                        //回滚
                        transactionStatus.setRollbackOnly();
                    }
    
                }
            });
    }
    

    编程式事务管理存在什么问题呢?

    如果我们有另一个业务代码需要进行事务控制,那我们就需要重复编写上面的事务逻辑代码。导致代码重复量大,于是人们提出了AOP面向切面编程。

    AOP,在不改变我们原有代码的前提下,将代码加强(增加事务)。

    那AOP是如何不改变原有代码,使得业务代码加强的呢?其实是基于代理模式。

    如果不懂代理模式的可以看一下尚**的视频,直达代理模式:https://www.bilibili.com/video/BV1G4411c7N4?p=94

    下面进行模拟

    目标:我们要增强Student的learn()方法(比如添加事务、日志、安全等)

    public class Student {
        public void learn() {
            System.out.println("student is learning!");
        }
    }
    
    public class ProxyFactory implements MethodInterceptor {
        //代理的对象
        private Object target;
    	
        //我们要代理的对象是哪一个就传进来哪一个(这里传进来的是Student)
        public ProxyFactory(Object target) {
            this.target = target;
        }
    
        //这个方法看不懂也没有关系,只需要知道它返回了一个代理对象(也就是target的代理对象,这里是Student的代理对象)
        public Object getProxyInstance() {
            //1. 实例化工具类
            Enhancer en = new Enhancer();
            //2. 设置父类
            en.setSuperclass(this.target.getClass());
            //3. 设置回调函数
            en.setCallback(this);
            //4. 创建子类,也就是代理对象
            return en.create();
        }
    
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("事务开始");
            //执行目标对象的方法
            Object returnVal = method.invoke(target, objects);
            System.out.println("事务结束");
            return returnVal;
        }
    
    }
    
    
    public static void main() {
        ProxyFactory proxyFactory = new ProxyFactory(new Plane());
        Student student = (Student) proxyFactory.getProxyInstance();
        student.learn();
    }
    

    最终输出

    事务开始
    student is learning!
    事务结束
    

    参考:

    中文官网:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/core.html

    IoC实现原理:https://blog.csdn.net/fuzhongmin05/article/details/61614873

    依赖注入:https://blog.csdn.net/xzp_12345/article/details/77885614
    有帮助的话,动个小指点个赞吧,欢迎关注我的公众号玩编程地码农,目前在写数据结构与算法、计算机基础、java相关的知识。

  • 相关阅读:
    SparkSQL【概述,DataFrame核心编程】
    【科学文献计量】标准参考出版年谱(Standard RPYS)和多维参考出版年谱(Multi RPYS)
    使用AOP进行日志记录
    2022,云大厂“猛砸”合作伙伴生态
    RabbitMQ中延迟队列的全方位解析
    自定义vue项目的雷达图组件
    使用 Lhotse 高效管理音频数据集
    2022年数据泄露平均成本高达435万美元,创历史新高!
    快速或者慢速:如何将视频调整为合适的播放速度
    小心golang中的无类型常量
  • 原文地址:https://www.cnblogs.com/wbcdmn/p/15897089.html