初步理解IOC和DI和AOP模式

控制反转(IOC)

控制反转(IOC,Inversion of Control)是一种转主动为被动关系的一种编程模式,有点类似于工厂模式,举个栗子,

下面这个这不是IOC模式

Interface interface{
// 啥也不写
}
class A implements interface{
String name;
}
class B implements interface{
Strng name;
}
class C{
interface AorB;
public C(){
AorB = new A();
}
}

在上面在这个例子,类C依赖于类A或类B。

这种方法有很多缺点,比如,如果类A的定义改了,比如说

第一点:增加了一个构造方法来动态设定name属性,那么那类A的定义,类C的实现,全部都要改。

第二点:如果要更改类C的实现,比如临时更改类C中的依赖的接口AorB的实现为类B,这个时候就要重新更改代码,将类C改为:

class C{
interface AorB;
public C(){
AorB = new B();
}
}

然后重新编译,重新运行,系统才能重新运作,特别麻烦。

要知道,在大型应用开发中,一个类依赖的可能不仅仅是一两个类,可能是一两百个,或者是几千个类,这个时候如果其中一个类要更改,则这几千个类的源码都要重新修改重新编译,

知乎上有个大神用了个比喻来描述这种情况:

需求是造一辆汽车。

从最基础的轮子开始造起,此时底盘是依赖于轮子的,车身依赖于底盘,整个汽车又依赖于车身,而底盘的具体形状是依赖于轮子的大小的。

试想一下,当你造的差不多的时候,客户跟你说,他觉得轮子大一点显得气派,要你把轮子造的大一圈。

而你的底盘是依赖于轮子的,所以你的底盘也要重新设计,车身是依赖于底盘的,所以你的车身也要重新设计,换句话说,你因为轮子的变动,不得不把整个汽车重新设计一遍。

很痛苦。

假定你要在轮子类的实现里面增加一个构造函数来动态的修改的他的大小,那么你就要在依赖于他的底盘类中也增加一个构造函数,然后,又要在车身类中增加一个构造函数。

形如下面的修改(红色是修改部分):

// 轮子

class Tire(){

private int size;

public Tire(int size){

this.size = size;

}

}

// 底盘类

class Bottom {

    private Tire tire; // 依赖于轮子

    public Bottom(int size) {

        tire = new Tire(size);

    }

}

// 车身类

class Framework {

    private Bottom bottom;

    public Framework(int size) {

        bottom = new Bottom(size);

    }

}

// 汽车类

可以看到,这基本就是牵一发而动全身的趋势。

运用IOC模式可以避免这种情况的发生,IOC模式让我们不主动创建类,创建类的任务交给IOC容器来做,换句话说,类中的属性,也完全不需要我们手动进行赋值,IOC容器会自动将这些属性用xml规定好的内容赋上(也就是依赖注入)。同时,创建的对象的生命周期也完全由IOC容器进行管理,而不用我们进行销毁啊,关闭啊之类的行动(只管用就行了= =)。

下面使用IOC容器(Spring)重做轮子,底盘,车身类

先编写xml

beans.xml

<?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-3.0.xsd">

<!-- 轮子类 -->

<bean id=”tire” class=”car.Tire”>

<property name=”size” value=4 />

</bean>

<!-- 底盘类 -->

<bean id=”bottom” class=”car.Bottom”>

<property name=”tire”>

<!-- 依赖轮子类 -->

<ref bean=”tire” />

</property>

</bean>

<!-- 车身类 -->

<bean id=”framework” class=”car.Framework”>

<property name=”bottom”>

<!-- 依赖轮子类 -->

<ref bean=”bottom” />

</property>

</bean>

<!-- 汽车类 -->

</beans>

下面编写bean,轮子类,底盘类,车身类

class Tire{

    private int size; // 大小

    size : set方法

}

class Bottom{

    private Tire tire;

    tire : set方法

}

class Framework {

    private Bottom bottom;

    bottom:set方法

}

要用这汽车类的时候,像下面这样编写。

// 编写测试类

class Test {

    public static void main(String[] args){

        // 得到IOC容器

        BeanFactory beanfactory = new XmlBeanFactory(new ClassPathResource(“beans.xml”));

        // 直接从容器里面拿车,而不需要自己手动new创建

        Car car = (Car)beanfactory.getBean(“car”);

    }

}

依赖注入(DI)

我觉得依赖注入算是实现控制反转的一个方法,抽象一点来说,IOC是一种设计模式,而DI就是实现这种设计模式的一种方法,常见的依赖注入的方法有下面这三种。

  1. 使用set方法注入属性
  2. 使用构造器注入属性
  3. 接口类型(这种我没看懂)

面向切面编程(AOP)

AOP我用的还不熟,现阶段感觉就是python里面的装饰器啊。。。。一堆听不懂的名词。。。。

认真的讲,AOP解决的问题是一个切面的问题,用书上的栗子来说明AOP的好处。

目前有一个任务,要你计算一个班上的学生的成绩的平均数,学生成绩放在一个数据库里

一般实现这个程序只需要三个步骤:

  1. 拿到班上所有同学的成绩
  2. 成绩相加/同学的总数
  3. 得到平均数

但实际上编程序的时候远远不止这三步,因为实际情况下,你要打开数据库,然后这个打开数据库的途中可以出现很多异常(数据库服务器没开,表名错了,连错数据库等等),这些我们都要一一解决,最后,得到平均数,关闭数据库的时候,也会有很多情况发生(各种SQL语句错误),这个时候,代码里面就会多了很多跟我们的业务逻辑不相关的内容(打开,关闭数据库,处理数据库异常),看起来不好看,同时代码耦合,改起来麻烦。

面向切面编程(AOP)解决了这个问题,他可以在链接数据库那个地方创建一个连接点,然后连接点处可以编写代码,专门解决这些数据库链接的问题,嗯,这听起来有点像在前面写个函数解决问题的。。。。但实际上不是这样的,用py的装饰器举个例子:

现在有一个函数,用循环从1加到10000.

def add():

  result = 0

  for i in range(10000):

    result += i

return result

现在有一个需求,就是计算这个函数的运行时间。

一般来说,就是在函数里面写个什么time.now(),然后在最后也来个time.now(),然后相减,得到运行时间,使用AOP模式不需要更改原本函数的一丝一毫的代码,下面是AOP模式(装饰器模式,Spring里面是代理模式实现AOP模式)

def getTime(func):

  def addfunction(*arg,*kargs):

    t1 = time.now()

    result = func(*arg,*kargs)

    t2 = time.now()

    print(‘运行时间是:’+(t2-t2))

    return result

return addfunction

没有对原本函数进行修改,达到了获得函数运行时间的效果,书上说这就是解决了横切关注点和调用者和被调用者之间的解耦问题。

初步理解IOC和DI和AOP模式的更多相关文章

  1. IOC和DI,AOP的本质理解

    IOC: Inversion of Control,控制反转, 控制权从应用程序转移到框架(如IOC容器),是框架共有的特性. 对于IOC的理解,可以把IOC看作是一个生产和管理bean对象的容器.原 ...

  2. 由浅入深理解 IOC 和 DI

    目录 由浅入深理解 IOC 和 DI 开闭原则 OCP(Open Closed Principle) 面向抽象编程 逐步理解实现 IOC 和 DI 的过程(LOL Demo 示例) 比较尴尬的编写程序 ...

  3. 对IOC和DI以及AOP的理解

    为了理解Spring的IoC与DI从网上查了很多资料,作为初学者,下面的描述应该是最详细,最易理解的方式了. 首先想说说IoC(Inversion of Control,控制倒转).这是spring的 ...

  4. SSM框架中IoC、DI与AOP的理解

    框架封装了普通项目中程序员需要重复书写的代码和调用过程,就比如说在传统的jsp项目中,我们的controller接收到前端的请求然后程序员就需要去开发Dao层,里面还涉及数据库的连接和存储过程的代码, ...

  5. Spring学习笔记--环境搭建和初步理解IOC

    Spring框架是一个轻量级的框架,不依赖容器就能够运行,像重量级的框架EJB框架就必须运行在JBoss等支持EJB的容器中,核心思想是IOC,AOP,Spring能够协同Struts,hiberna ...

  6. Spring自学教程-IOC、DI、AOP(二)

    一.spring的IOC-就是怎样使用spring来创建对象 二.springDI(依赖注入)-就是怎样给属性赋值 通过set方式赋值 以下我们只需要记住两点的赋值,基本类型和引用类型的赋值 基本类型 ...

  7. 深入理解IoC和DI

    本文章转载自: https://segmentfault.com/a/1190000005602011 最近在研究php的lumen框架和phalcon框架,这两个框架的底层架构都用到了IoC,DI, ...

  8. Spring入门一:IOC、DI、AOP基本思想

    Spring框架是一个集众多涉及模式于一身的开源的.轻量级的项目管理框架,致力于javaee轻量级解决方案.相对于原来学过的框架而言,spring框架和之前学习的struts2.mybatis框架有了 ...

  9. 简单理解IoC与DI

    为了理解Spring的IoC与DI从网上查了很多资料,作为初学者,下面的描述应该是最详细,最易理解的方式了. 首先想说说IoC(Inversion of Control,控制倒转).这是spring的 ...

随机推荐

  1. 1 数据库开发--MySQL介绍

    1.数据库管理软件 C/S 并发.锁 :SQL语句.语法 基本管理和语法学习 一.介绍: mysql数据库管理软件: 套接字:服务端,客户端:客户端可访问服务端得数据 1.支持并发:操作得是共享得数据 ...

  2. java中getAttribute和getParameter的区别

    getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型 getParame ...

  3. Python运维开发基础09-函数基础

    上节作业回顾 #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 实现简单的shell命令sed的替换功能 import ...

  4. maven exclusions version

    <dependency> <groupId>cn.wonhigh</groupId> <artifactId>base-framework-web< ...

  5. 利用 Chrome 原生工具进行网页长截图

    转自https://sspai.com/post/42193 要想使用截图功能,你需要首先确保 Chrome 已升级至 59 或更高版本.在想要截图的网页中,首先按下 ⌘Command + ⌥Opti ...

  6. 向值栈放List集合

    ------------------siwuxie095 向值栈放 List 集合 1.具体步骤 (1)在 Action 中定义 List 集合对象 (2)提供 List 集合对象的 get 方法 ( ...

  7. mybatis框架入门程序:演示通过mybatis实现数据库的修改操作

    1.mybatis的基本配置工作可以在我的这篇博客中查看:https://www.cnblogs.com/wyhluckdog/p/10149480.html 2.修改用户的配置文件: <upd ...

  8. COGS 2189 帕秋莉的超级多项式

    放模板啦! 以后打比赛的时候直接复制过来. 说句实话vector的效率真的不怎么样,但是似乎也还行,最主要是……写得比较爽. #include <cstdio> #include < ...

  9. python之selenium调用js(execute_script)

    转载: http://www.cnblogs.com/fnng/p/3230768.html 本节重点: 调用js方法 execute_script(script, *args) 在当前窗口/框架 同 ...

  10. windows聚焦图片文件重命名bash脚本

    win10聚焦路径为: %localappdata%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalStat ...