依赖注入(DI)的使用和Spring AOP(面向切面编程)

依赖注入的使用

  • 以打印机案例深入理解依赖注入
    要实现打印机需要创建墨盒Ink接口以及纸张Paper接口
public interface Ink {
    public  String getColor(int r,int g ,int b);
}

public interface Paper {
    public static final String newLine="\r\n";
    //输出一个字符到纸张
    public void putInChar(char c);
    //得到输出到纸张上的内容
    public String getContent();
}

使用墨盒和纸张接口开发打印程序Printer

public class Printer {
    private Ink ink=null;
    private Paper paper=null;

    public void setInk(Ink ink) {
        this.ink = ink;
    }

    public void setPaper(Paper paper) {
        this.paper = paper;
    }

    public void print(String str){
        System.out.println("使用"+ink.getColor(255,200,0)+"颜色打印:\n");
        for (int i = 0; i <str.length() ; i++) {
            paper.putInChar(str.charAt(i));
        }
        System.out.println(paper.getContent());
    }
}

编写纸张,彩色 灰色墨盒以及打印纸的实现类

//彩色墨盒
public class ColorInk implements Ink {
    @Override
    public String getColor(int r, int g, int b) {
      Color color = new Color(r, g, b);
        return "#"+Integer.toHexString(color.getRGB()).substring(2);
    }
}
//灰色墨盒
public class GeryInk implements Ink {
    @Override
    public String getColor(int r, int g, int b) {
        int c=(r+g+b)/3;
        Color color = new Color(c,c,c);
        return "#"+Integer.toHexString(color.getRGB()).substring(2);
    }
}

public class TextPaper implements Paper {
    private int charPerLine = 16;

    private int linePerPage = 5;

    private String content = "";

    private int posX = 0;

    private int posY = 0;

    private int posP = 1;


    @Override
    public void putInChar(char c) {
         content+=c;
         ++posX;
         if (posX==charPerLine){
             content+=Paper.newLine;
             posX=0;
             ++posY;
         }
         if (posY==linePerPage){
             content +="==第"+posP+"页==";
             content+=Paper.newLine+Paper.newLine;
             posY=0;
             ++posP;
         }
    }
    public void setCharPerLine(int charPerLine){
        this.charPerLine=charPerLine;
    }
    public  void setLinePerPage(int linePerPage){
        this.linePerPage=linePerPage;
    }
    @Override
    public String getContent() {
        String ret = this.content;
        if (!(posX == 0 && posY == 0)) {
            int count = linePerPage - posY;
            for (int i = 0; i < count; i++) {
                ret += "==第" + posP + "页==";
            }
        }
        return ret;
    }
}

配置打印机的xml文件spring_Context.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.xsd">
        <bean id="greyInk" class="com.bdqn.IOC.GeryInk"/>
        <bean id="colorInk" class="com.bdqn.IOC.ColorInk"/>
    <bean id="a4paper" class="com.bdqn.IOC.TextPaper">
        <property name="charPerLine" value="10"/>
        <property name="linePerPage" value="80"/>
    </bean>
    <bean id="b5paper" class="com.bdqn.IOC.TextPaper">
        <property name="charPerLine" value="6"/>
        <property name="linePerPage" value="5"/>
    </bean>

    <bean id="printer" class="com.bdqn.IOC.Printer">
        <property name="ink" ref="colorInk"/>
        <property name="paper" ref="b5paper"/>
    </bean>
</beans>

编写测试类

 @Test
 public void TestPrint(){
    ApplicationContext context = new ClassPathXmlApplicationContext("spring_Context.xml");
     Printer printer=(Printer) context.getBean("printer");
     String content="控制反转也称依赖注入,是面对对象编程中的一种设计理念,用于降低程序代码间的耦合度。在不使用Spring时,创建对象需要我们主动去new," +
             "A和B要一起完成一件事,A需要用到B这件事才能做到,这就叫A对B产生了依赖,使用了Spring以后,不需要我们去手动new对象," +
             "把new对象的权利交给了第三方,这样A就不再依赖于B,所以控制反转I是说创建对象的控制权进行转移," +
             "以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方\n";
     printer.print(content);
 }
}

测试结果如下:
依赖注入(DI)的使用和Spring AOP(面向切面编程)

—分割线-----------

Spring AOP(面向切面编程)

面向切面编程AOP(Aspect Oriented Programming)是编程软件思想发展到一定阶段的产物,是面向对象编程的有益补充,AOP一般适用于具有横切逻辑的场合,如访问控制,事务管理,性能检测等。
面向切面编程AOP的基本概念

  1. 切面(Aspect):一个模块化的横切逻辑,可能会横切多个对象。
  2. 连接点(Join Point):程序执行中的某个具体执行头。
  3. 增强处理(Advice):切面在某个特定连接点上执行的代码逻辑
  4. 切入点(Pointcut):对连接点的特征进行描述,可以使用正则表达式。增强处理和一个切入点表达式相关联,并在与这个切入点匹配的某个连接点上运行。
  5. 目标对象(Target object):被一个或多个切面增强的对象。
  6. AOP代理(AOP proxy):由AOP框架所创建的对象,实现执行增强处理方法等功能。
  7. 织入(Weaving):将增强处理连接到应用程序中的类型或对象上的过程。
  8. 增强处理类型:前置增强,后置增强,环绕增强,异常抛出异常,最终增强等。

前置增强,后置增强,后置增强带返回值,后置增强带异常的实现
首先需要编写俩个类,一个为目标增强类命名为Target,一个增强类AdviceTarget。

public class Target {
    public  String   show(String name){
        System.out.println("这是目标方法");
        return "hello"+name;
    }
}


//增强类
public class AviceTarget {
    //前置增强
    public void  before(JoinPoint jp){
        System.out.println( "参数:"+jp.getArgs()+"方法名"+jp.getSignature()+"目标对象"+jp.getTarget());
    }
    //后置增强
    public void after(JoinPoint jp){
        System.out.println("这是后置");
    }
    //后置增强带返回值
    public void afterReturn(JoinPoint jp ,String value){
        System.out.println("这是后置带返回值"+value);
    }
    //后置增强带异常
    public  void afterException(JoinPoint jp , Exception ex) throws Exception {
        System.out.println("后置带异常"+ex);
        if (1/0==1){
            throw new Exception("除数不为0");
        }
    }
}

编写增强的xml文件spring_aop.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" 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="target" class="com.bdqn.aop.Target"/>     <!--增强目标类bean-->
    <bean id="advicetarget" class="com.bdqn.aop.AviceTarget"/>      <!--增强类bean-->

    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(public String show(String ))"/>    <!--设置切入点,切入点为Target类的show()方法-->
        <aop:aspect ref="advicetarget">
            <aop:before method="before" pointcut-ref="pointcut"></aop:before>    <!--前置增强-->
            <aop:after method="after" pointcut-ref="pointcut"></aop:after>       <!--后置增强-->
            <aop:after-returning method="afterReturn" pointcut-ref="pointcut" returning="value"></aop:after-returning>       <!--后置增强带返回值-->
           <aop:after-throwing method="afterException"  pointcut-ref="pointcut" throwing="ex"></aop:after-throwing>      <!--后置增强带异常-->
        </aop:aspect>
    </aop:config>

</beans>

编写测试类 把上面四个都写在了一个测试类

@Test
public void TestAop(){
    ApplicationContext context = new  ClassPathXmlApplicationContext ("spring_aop.xml");
    Target target=(Target) context.getBean("target");

    try {
        target.show("mary0");
    } catch (Exception e) {
        e.printStackTrace();
    }

}

测试结果
依赖注入(DI)的使用和Spring AOP(面向切面编程)