AOP,IOC,DI介绍,看完吊打面试官

1. Spring的特点

  1. 轻量级
  2. 控制反转(IOC)
  3. 面向切面 (AOP)
  4. 容器

简单来说,Spring是一个轻量级得到控制反转和面向切面的容器框架
至于IOC和AOP则是Spring的灵魂,这两点搞清楚,Spring就很容易理解了,下面我就来介绍这两个特性

AOP是什么?

AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。

横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”

2. IOC是什么

IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”。控制反转是依赖倒置原则的一种代码设计思想。具体采用的方法就是所谓的依赖注入(DI)

在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

3. DI和IOC的关系

DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  1. 谁依赖于谁:当然是应用程序依赖于IoC容器;
  2. 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
  3. 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
  4. 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”

Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:

  1. 构造方法注入
  public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    <bean class="com.ujiuye.demo.pojo.Human" id="human4">
        <constructor-arg name="name" value="aa"/>
        <constructor-arg name="age" value="21"/>
    bean>
  1. setter注入
 public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    <bean class="com.ujiuye.demo.pojo.Human" id="human5">
        <property name="name" value="dd"/>
        <property name="age" value="12"/>
    bean>
  1. 基于Array注入
 private String[] arr;
 public String[] getArr() {
        return arr;
    }

    public void setArr(String[] arr) {
        this.arr = arr;
    }
<bean class="com.ujiuye.demo.pojo.Human" id="human6">
        <property name="arr">
            <array>
                <value>avalue>
                <value>bvalue>
                <value>cvalue>
                <value>dvalue>
            array>
        property>
    bean>
  1. List注入
 private List<String> list;
   public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    <bean class="com.ujiuye.demo.pojo.Human" id="human7">
        <property name="list">
           <list>
               <value>aavalue>
               <value>bbvalue>
               <value>ccvalue>
               <value>ddvalue>
           list>
        property>
    bean>
  1. Set注入
    private Set<String> set;
    public Set<String> getSet() {
        return set;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }
 
    <bean class="com.ujiuye.demo.pojo.Human" id="human8">
        <property name="set">
            <set>
                <value>aaavalue>
                <value>bbbvalue>
                <value>cccvalue>
                <value>dddvalue>
            set>
        property>
    bean>
  1. Map注入
   private Map<String, String> map;
    <!--map注入-->
    <bean class="com.ujiuye.demo.pojo.Human" id="human9">
        <property name="map">
            <map>
                <entry key="x" value="X"></entry>
                <entry key="y" value="Y"></entry>
                <entry key="z" value="Z"></entry>
            </map>
        </property>
    </bean>
  1. Properties注入
 private Properties properties;
   <!--Properties注入-->
    <bean class="com.ujiuye.demo.pojo.Human" id="human10">
        <property name="properties">
            <props>
                <prop key="h">H</prop>
                <prop key="j">J</prop>
                <prop key="k">K</prop>
            </props>
        </property>
    </bean>
  1. 对象属性的注入
    private Dog dog;
    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }
 
    <bean class="com.ujiuye.demo.pojo.Dog" id="dog">
        <property name="age" value="2"/>
        <property name="name" value="d"/>
    bean>
    <bean class="com.ujiuye.demo.pojo.Human" id="human11">
        <property name="dog" ref="dog"/>
    bean>
beans>

IOC和DI的区别

AOP,IOC,DI介绍,看完吊打面试官_第1张图片

  • 站在person的角度car是属性, car的注入就是DI
  • 站在car的角度, car的创建是IOC

4. Spring的模块

Spring框架至今已集成了20多个模块。这些模块主要被分如下图所示的核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。

AOP,IOC,DI介绍,看完吊打面试官_第2张图片

spring 事务实现方式有哪些?

  1. 编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
  2. 基于 TransactionProxyFactoryBean 的声明式事务管理
  3. 基于 @Transactional 的声明式事务管理
  4. 基于 Aspectj AOP 配置事务

你可能感兴趣的:(JavaEE,spring,java)