Spring-IOC与AOP是解决什么问题的?

阅读更多
 

1.1         框架需求分析

1.1.1        问题描述:编码依赖问题

在程序中要分层,且层与层相互调用就会存在依赖, 下面代码同学们应该不会陌生:

publicclass StudentAction {

    /*

     * 采用new的方式创建业务逻辑层,为硬编码的方式

     * 这种方式缺乏灵活性,后期维护则需要编译class文件之后覆盖原来的class文件

     * 这种方式也体现不出面向接口编程的好处

     */

    private StudentService studentService = new StudentServiceimpl();

    private Student student;

    public Student getStudent() {

       returnstudent;

    }

    publicvoid setStudent(Student student) {

       this.student = student;

    }

    public String save() {

       studentService.save(student);

       return"success";

    }

}

 

同样在业务逻辑层调用数据访问层中,也会出现如下问题:

publicclass StudentServiceimpl implements StudentService {

    /*

     * 如果底层切换的数据库,则数据访问层也要切换, 但是目前new 之后不方便修改

     * */

    private StudentDao studentDao=new StudentDaoImpl();

    publicvoid save(Student student) {

       studentDao.save(student);

    }

}

以上代码是有问题的,即在控制层中依赖了具体的业务逻辑层, 在业务逻辑层中依赖了具体的数据访问层. 这样就和具体的实现类耦合在了一起,也没有发挥面向接口编程的作用. 如果要更换(比如要换成StudentDaoOracleImpl),就需要修改源代码,但是项目很多模块都需要同时修改,这样会非常麻烦. 而且修改完毕之后还要编译成class文件,覆盖原来的文件. 不利于项目的后期维护, 而且项目与项目之间的依赖隐藏在了代码中.也不适合全局把握正个项目, 因此维护性和二次开发比较麻烦

1.1.2        解决方案1:工厂模式

可以使用抽象工厂, StudentDao StudentService的实现在在工厂中生成,而工厂可以根据配置文件的指定类型,来创建不同的对象, 而且工厂本身一般是不变的. 从而降低了对可以变的业务逻辑类的依赖, 接近的软件的设计目标高内聚,低耦合

控制层à抽象工厂à业务逻辑层

publicclass StudentAction {

    /*

     * 依赖具体的对象,改为依赖工厂, 而工厂创建的路径来自具体的配置文件,所以灵活性大大提高

     * 必须要声明为接口类型,否则工厂没有任何意义(面向接口编程)

     * */

    private StudentService studentService=(StudentService)BeanFactory.getBean("studentService");

    private Student student;

    public Student getStudent() {

       returnstudent;

    }

    publicvoid setStudent(Student student) {

       this.student = student;

    }

    public String save() {

       studentService.save(student);

       return"success";

    }

 

}

业务逻辑层à抽象工厂à数据访问层

publicclass StudentServiceImpl implements StudentService {

    /*

     * 依赖工厂,降低耦合度,可以根据配置灵活修改创建的对象

     * */

    private StudentDao studentDao=(StudentDao)BeanFactory.getBean("studentDao");

    publicvoid save(Student student) {

       studentDao.save(student);

    }

}

以上代码就是通过抽象工厂来实现层与层之间的解耦,这种情况下如果想要更新别外一个实现类,只需要修改配置文件就可以了, 注意这里只是降低了层与层之间的复杂度, 并没有让耦合消失, 实际上层与层是不可能没有耦合的,我们学框架的目的就是要找到变的部分,然后用配置文件来配置这样修改的时候修改配置文件就OK, 不需要修改代码本身

但是有时候有些类创建的时候需要单例模式, 有的则需要多个实例、还有不同的类在创建的时候有些类需要初始化操作, 有些又不需要初始化数据…..这又怎么办呢?那就要再完善一下这个工厂类了, 或者多创建一些工厂了. 让工厂可以处理这些问题, 但是我们自己实现起来就复杂了

1.1.3        解决方案2: IOC依赖注入

所谓依赖注入就是指:在运行期,由外部配置文件动态地将本身所依赖对象通过set方法注入到组件中,我们只需要用即可,而不需要在去管理对象的创建和销毁, 我们期望的代码应该是如下:

publicclass StudentAction {

    // 只要符合接口类型,就可以注入进来,这样我们都不需要依赖工厂

    private StudentService studentService=null;

    // 通过set方式,在运行期间注入

    publicvoid setStudentService(StudentService studentService) {

       this.studentService = studentService;

    }

private Student student;

    public Student getStudent() {

       returnstudent;

    }

    publicvoid setStudent(Student student) {

       this.student = student;

    }

    public String save() {

       studentService.save(student);

       return"success";

    }

}

或者如下代码:

publicclass StudentServiceImpl implements StudentService {

    // 只要符合接口类型,就可以注入进来,这样我们都不需要依赖工厂

private StudentDao studentDao=null;

    publicvoid save(Student student) {

       studentDao.save(student);

    }

}

1.1.4        问题描述: 编程式事务

publicvoid save(Student student){

       Session session=HibernateSessionFactory.getSession();

       // 手动控制的事务称为编程时事务

       try {

           session.getTransaction().begin();

           session.save(student);

           session.getTransaction().commit();

       } catch (HibernateException e) {

           e.printStackTrace();

           session.getTransaction().rollback();

       }finally{

           HibernateSessionFactory.closeSession();

       }

    }

以上代码是有问题的, 红色的部分, 每次只要有数据修改操作的时候则都要编写, 更重要的是这些代码与方法的功能本身又没有紧密的联系.而且基本每个模块都有, 重复的代码大大降低了我们的效率和增加了维护的成本,

1.1.5        解决方案1: 代理模式

// 创建一个代理类,来完成Session事务的提交、回滚

publicclass SessionProxy implements Session {

    private Session session = null;

    public SessionProxy(Session session) {

       this.session = session;

    }

    publicvoid begin() {

       session.getTransaction().begin();

    }

    publicvoid rollback() {

       session.getTransaction().rollback();

    }

    publicvoid save(Student student) {

       try {

           this.begin();

           session.save(student);

       } catch (Exception e) {

           this.rollback();

       } finally {

           this.commit();

       }

    }

    publicvoid commit() {

       session.getTransaction().commit();

    }

}

数据访问层代码修改如下:

    publicvoid save(Student student){

       // HibernateSessionFactory返回的是session的代理

       SessionProxy sessionProxy=HibernateSessionFactory.getSession();

       // 代理的save中调用了 begin commit 或者rollback

       sessionProxy.save(student);

    }

代理缺点:不灵活,以后修改了接口, 代理类也要维护. 而且代理的类型受到接口的制约, 但是我们的事务基本所有的业务逻辑模块都有. 所以此方法不易推广

1.1.6        解决方案2: AOP声明式事务


Spring-IOC与AOP是解决什么问题的?_第1张图片
 

 

 

 

 

 

  • Spring-IOC与AOP是解决什么问题的?_第2张图片
  • 大小: 11.6 KB
  • 查看图片附件

你可能感兴趣的:(Spring3.0,aop,IOC)