总结-对各种开源框架的认识小结-spring

来源:互联网 发布:淘宝会员管理系统 编辑:程序博客网 时间:2024/05/16 12:49
作为一个入门级java程序员,最重要的还是总结和积累。上一个总结的框架是struts2,下面再记录一个更加常用的框架-spring。

何为spring

Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发.

为什么要使用spring

1.降低组件之间的耦合度,实现软件各层之间的解耦
2.可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。
3.容器提供单例模式支持,开发人员不再需要自己编写实现代码。
4.容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。
5.容器提供的众多辅作类,使用这些类能够加快应用的开发,如: JdbcTemplate、 HibernateTemplate。
6.Spring对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发。

IOC(Inversion of Control)

概念:控制反转,在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制反转。

IOC和DI:依赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。
网友wm5920解释:

IOC控制反转:说的是创建对象实例的控制权从代码控制剥离到IOC容器控制,实际就是你在xml文件控制,侧重于原理。
DI依赖注入:说的是创建对象实例时,为这个对象注入属性值或其它对象实例,侧重于实现。

核心:spring中BeanFacotory是IoC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。XmlBeanFacotory实现BeanFactory接口,通过获取xml配置文件数据,组成应用对象及对象间的依赖关系。
spring ioc中有三种依赖注入,分别是:a、接口注入;b、setter方法注入;c、构造方法注入;下面来看看这三种注入方法的区别。

  • 接口注入
    先看代码实现:
public class ClassA {    private InterfaceB clzB;    public void doSomething() {      Ojbect obj = Class.forName(Config.BImplementation).newInstance();      clzB = (InterfaceB)obj;      clzB.doIt();     }  ……  }  

如果类A需要依赖接口B,传统方法:在A中通过B的实体类进行实例化,然后赋值给clzB,这样来说ClassA在编译期即依赖于InterfaceB的实现。依赖注入:根据预先在配置文件中设定的实现类的类名(Config.BImplementation),动态加载实现类,并通过InterfaceB强制转型后为ClassA所用,这就是接口注入的一个最原始的雏形。

  • setter方法注入
<bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">       <!-- (1)userManager使用了userDao,Ioc是自动创建相应的UserDao实现,都是由容器管理-->            <!-- (2)在UserManager中提供构造函数,让spring将UserDao实现注入(DI)过来 -->            <!-- (3)让spring管理我们对象的创建和依赖关系,必须将依赖关系配置到spring的核心配置文件中 -->            <property name="userDao" ref="userDao4Oracle"></property>    </bean>  
public class UserManagerImpl implements UserManager{        private UserDao userDao;        //使用设值方式赋值        public void setUserDao(UserDao userDao) {            this.userDao = userDao;        }        @Override        public void addUser(String userName, String password) {            userDao.addUser(userName, password);        }    }    
  • 构造方法注入
<bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">                <!-- (1)userManager使用了userDao,Ioc是自动创建相应的UserDao实现,都是由容器管理-->                <!-- (2)在UserManager中提供构造函数,让spring将UserDao实现注入(DI)过来 -->                <!-- (3)让spring管理我们对象的创建和依赖关系,必须将依赖关系配置到spring的核心配置文件中 -->                <constructor-arg ref="userDao4Oracle"/>    </bean>    
 public class UserManagerImpl implements UserManager{            private UserDao userDao;            //使用构造方式赋值            public UserManagerImpl(UserDao userDao) {                this.userDao = userDao;            }            @Override            public void addUser(String userName, String password) {                userDao.addUser(userName, password);            }        }    
  • 三种注入方法比较

接口注入:
接口注入模式因为具备侵入性,它要求组件必须与特定的接口相关联,因此并不被看好,实际使用有限。
Setter 注入:
对于习惯了传统 javabean 开发的程序员,通过 setter 方法设定依赖关系更加直观。如果依赖关系较为复杂,那么构造子注入模式的构造函数也会相当庞大,而此时设值注入模式则更为简洁。如果用到了第三方类库,可能要求我们的组件提供一个默认的构造函数,此时构造子注入模式也不适用。
构造器注入:
在构造期间完成一个完整的、合法的对象。所有依赖关系在构造函数中集中呈现。依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中。

AOP(Aspect-OrientedProgramming)

  1. 概念
    将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

  2. 使用场景
    Authentication 权限
    Caching 缓存
    Context passing 内容传递
    Error handling 错误处理
    Lazy loading 懒加载
    Debugging  调试
    logging, tracing, profiling and monitoring 记录跟踪 优化 校准
    Performance optimization 性能优化
    Persistence  持久化
    Resource pooling 资源池
    Synchronization 同步
    Transactions 事务

  3. 使用示例
    模拟一个用户登录注册的场景,首先有一个用户接口如下:

public interface IUser {    public void reg();    public void login();}

原本要写一个接口的实现类来实现两个方法,但是分别有注册前后和登录前后要执行的方法:

public class PUser implements IUser {    @Override    public void reg() {        // 业务前执行的方法        // ....        System.out.println("注册前的执行方法");        //业务执行        System.out.println("注册");        // 业务后执行的方法        // ....        System.out.println("注册后的执行方法");    }    @Override    public void login() {        // 业务前执行的方法        // ....        System.out.println("登录前执行的方法");        System.out.println("登录");        // 业务后执行的方法        // ....        System.out.println("登录后执行的方法");    }}

假设登录和注册前后的执行方法一样,那么我们就可以把业务前后的执行方法提取出来,这里有通知前后和环绕通知三种方法 :

public class MyAdvice {    //通知前    public void brfore() {        System.out.println(" 业务前执行的方法");    }    //通知后    public void after() {        System.out.println(" 业务后执行的方法");    }    //环绕通知    public Object around(ProceedingJoinPoint pjp)  {      Object object=null;        try {            System.out.println(" 业务前执行的方法");             object =pjp.proceed();             System.out.println(" 业务后执行的方法");        } catch (Throwable e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return object;    }    public void except() {        System.out.println("异常通知打印日志!!!");    }}

最后在配置文件里加入相应配置即可:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"    xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-3.0.xsd    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">    <!-- 声明一个业务对象 -->    <bean id="u" class="PUser" />    <!-- 声明一个通知对象 -->    <bean id="adv" class="MyAdvice" />    <!-- 配置通知如何切入 -->    <aop:config>        <!-- 配置一条切线 -->        <aop:pointcut expression="execution(* IUser.*(..))"            id="pc" />        <!-- 配置一个切面 -->        <aop:aspect ref="adv">                  <!-- 通知前 -->            <aop:before pointcut-ref="pc" method="brfore()" />            <!-- 通知后 -->            <aop:after pointcut-ref="pc" method="after()" />            <!-- 环绕通知 -->            <aop:around pointcut-ref="pc" method="around" />            <!-- 配置异常通知日志打印 -->            <aop:after-throwing pointcut-ref="pc" method="except" />        </aop:aspect>    </aop:config></beans>
1 0