zoukankan      html  css  js  c++  java
  • 5分钟简述Spring中的DI与AOP

    Spring的两个核心特性:

    • 依赖注入(dependency injection,DI)
    • 面向切面编程(aspect oriented programming,AOP)

    依赖注入(dependency injection,DI)

    • 没有使用依赖注入时:以前每个POJO(Plain Ordinary Java Object,简单的Java对象)在创建的时候会主动的去获取依赖。从代码上的体现是一个类中有实例化另一个类的对象(耦合度高)。我们需要将相互协作的对象引用赋给它。
    • 三种依赖注入方式:setter方法注入,构造器注入,接口注入(就是在接口中声明一个方法,参数是依赖的对象)。
    • 依赖注入作用:将各个相互协作的模块代码保持松散耦合。
    • 下面我们通过几个简单的类来了解一下依赖注入:

    先声明两个接口People与Fruit。

    public interface People {// people接口
        void eat();
    }
    
    public interface Fruit {// 水果接口
        void speak();
    }

    接下来是分别实现他们的类Watermelon与Student。

    public class Watermelon implements Fruit{// 西瓜类
        @Override
        public void speak() {
            System.out.println("我是西瓜,我要被吃掉了!");
        }
    }
    
    public class Student implements People {// 学生类
        private Fruit fruit;
    
        public Student(Fruit fruit) {// 构造器注入依赖的对象
            this.fruit = fruit;
        }
    
        @Override
        public void eat() {
            fruit.speak();
        }
    }

    到这里我们可以看出Student类依赖Watermelon类。当调用Student的eat方法时需要调用Watermelon的speak方法。

    我们接下来用XML对这两个应用组件进行装配(wiring)。

    <?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">
    
        <!--水果声明为Spring的bean-->
        <bean id="fruit" class="com.qsh.springaction.Watermelon"/>
        <!--人声明为Spring的bean-->
        <bean id="people" class="com.qsh.springaction.Student">
            <constructor-arg ref="fruit"/>
        </bean>
    </beans>

    最后我们进行测试。用spring上下文全权负责对象的创建和组装。

    public class TestEat {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("eat.xml");
            People people = context.getBean(People.class);
            people.eat();
            context.close();
        }
    }

    测试结果。

    面向切面编程(aspect oriented programming,AOP)

    • 是什么:促使软件系统实现关注点分离的一项技术。系统由许多不同组件构成,每个组件负责一块特定功能。除了实现自身核心功能外,这些组件还承担着额外职责,如日志,事务管理和安全这样的系统服务,这样的系统服务被称为横切关注点。因为他们会横跨多个组件。
    • 作用:有助于横切关注点与它们所影响的对象之间的解耦。
    • 个人理解:每个组件除了实现自身的功能,还需要实现其他的如事物管理等功能(称为横切关注点)。我们将这功能单独抽取出来成一个模块,每个组件在工作的过程中,这个模块神不知鬼不觉的为每个组件实现额外功能。
    • 个人理解的切面图:应用组件:实现各自功能的代码。横切关注点:每个组件的额外业务,相同的代码。切面:将横切关注点模块化出来的一个类。连接点:应用执行时能够插入切面的点(超级多)切点:匹配其中一个或多个连接点。

     

    • 通过几段代码讲解AOP:

    我们还是有上面的Student 和 Watermelon类。需要新增加一个Action类,就是一会的切面。

    public class Action {// 行为类
    
        public void beforeEat() {
            System.out.println("吃前拿刀,嚓嚓嚓");
        }
    
        public void afterEat() {
            System.out.println("吃后洗手,哗哗哗");
        }
    }

    需要在XML中加入Spring AOP命名空间,将Action方法声明为Spring的bean,然后切面引用这个bean。切点为student的eat方法,在切点前后加入前置通知和后置通知。

    <?xml version="1.0" encoding="UTF-8" ?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
        <!--水果声明为Spring的bean-->
        <bean id="fruit" class="com.qsh.springaction.Watermelon"/>
        <!--人声明为Spring的bean-->
        <bean id="people" class="com.qsh.springaction.Student">
            <constructor-arg ref="fruit"/>
        </bean>
        <!--行为声明为Spring的bean-->
        <bean id="action" class="com.qsh.springaction.Action"/>
    
        <!--用spring aop的命名空间把Action声明为一个切面-->
        <aop:config>
            <!--引用Action的bean-->
            <aop:aspect ref="action">
                <!--声明Student的eat方法为一个切点-->
                <aop:pointcut id="eating" expression="execution(* *.eat(..))"/>
                <!--前置通知,在调用eat方法前调用Action的beforeEat方法-->
                <aop:before pointcut-ref="eating" method="beforeEat"/>
                <!--后置通知,在调用eat方法后调用Action的afterEat方法-->
                <aop:after pointcut-ref="eating" method="afterEat"/>
            </aop:aspect>
        </aop:config>
    </beans>

    运行结果为:

  • 相关阅读:
    超级楼梯
    hdu1040
    hdu2033(惭愧)
    hdu2032杨辉三角
    hdu1013Digital Roots
    hdu2031
    Linux信号(signal) 机制分析
    android init重启service(进程)
    [android] init进程 .rc文件中service、action的parsing
    oom_adj
  • 原文地址:https://www.cnblogs.com/JimKing/p/8759132.html
Copyright © 2011-2022 走看看