天天看点

Spring FrameWork 读书笔记

《Spring 开发指南》 台湾知名专家夏昕编写,以前在图书馆偶尔翻阅过,今天得到这本电子书,感觉还是蛮不错的,虽然讲的比较浅,没有深入浅出Hibernate讲的那么深,但在工作中使用还是绰绰有余的。

一   控制反转IOC(Inversion of Control) 也叫依赖注入(Dependence Injection)是由容器控制控制程序之间的关系而非由代码直接控制

二   注入方法:

      (1)、接口注入

                 doGet(HttpServletRequest request,HttpServletResponse response){}

              其中HttpServletRequest和HttpServletResponses实例是由Servlet Container容器在运行时动态注入,(依赖关系是在运行时建立的,将调用者和实现者在编译时分离).

     (2)、设置注入

                通过Setter 和getter方法来注入(常用)

     (3)、构造子注入

                 public class DIConstructor{

                          private final DataSource dataSource;

                         private final Stirng message;

                         public DIConstructor(DataSource dataSource,String message){

                                           this.dataSource=dataSource;

                                           this.message=message;

                        }  

                 }

                依赖关系是通过类的构造函数建立,容器通过调用类的构造函数方法,将其需要的依赖关系注入其中。

四  面向方面AOP(Aspect oriented programmer)

         与OOP的区别:OOP可以对雇员进行封装成一个类,并将相应的属性和行为封装其中,是对实体进行封装,而AOP是对业务处理这一切面进行提取。即:OOP面向名字领域,AOP面向动词领域。如”权限检查“这一动作片断。

Spring FrameWork 读书笔记

  1)、连接点(JoinPoint) 程序运行到某个阶段点,如:某个方法调用,抛出异常

  2)、处理逻辑(Advice) 连接点采用的处理逻辑

           Around  在连接点前后插入预处理的过程和后处理的过程

           Before   仅仅在连接点之前插入预处理过程

           Throw    连接点抛出异常时进行异常处理

3)、切点(PintCut)一系列连接点的集合,它指明处理方式(Advice)将在何时触发,比如事务管理中ops中的prop<prop key="save*"></prop>表明在插入是触发。

五、Spring 基本概念

(1) Spring 是轻量级且非侵入性,说它是轻量级的是因为它不依赖容器。说它非侵入性是因为应用独立。不依赖于任何容器。

    和EJB的区别:EJB称之为重量级是因为必须要依赖依赖EJB容器。侵入性高,当要把应用单独拿出来时,不容易,因为应用必须依赖容器,离开容器编译都通不过。虽然EJB 也提供事务管理,但必须是EJB组件才可以,而Spring提供声明是事务,只要是普通的对象pojo就可以声明是事务。

(2) 装配依赖关系IOC(Inversion Of Control)控制反转思想。依赖关系不是客户去做,比如创建对象,建立关系。而是交给IOC容器去管理(主动权给了IOC容器)。在配置文件中把所有关系都配好。当一个组件依赖另一个组件时。并且这种关系已经在IOC容器中配置好了,当A需要B时自动会拿到B,自动会把B new好给A,但是A必须提供构造函数,或者必须实行set(A a)方法,把new 好的对象给A。这个就称之为依赖注入DJ(Dependency Injection);DJ是实现依赖关系的一种方法,还有一种叫依赖查找。

ej

public class A{

   public save(new B());这个是普通的A依赖B关系,A要使用B。就要请求一对象

}

public class A{

  public B b;

  (1) 构造方法注入法

  public A(B b){

   this.b = b;

  }

  (2) set方法注入法

  public void setB(B b){

    this.b = b;

  }//通过setB();方法,B主动把自己的对象给A,也就是B是主动,A是被动。这就是DJ思想。

}

(3) AOP 比如Filter思想,对方法在执行前做什么,执行后做什么,抛异常做什么

(4) 与其它框架的集成。比如:Struts Hibernate。提供Session和事务管理。而使客户只关心业务就可以了。其它事情都不用担心。

六:applicationContext.xml文件的编写

<beans>

<!-- 普通bean --->

<bean id="bean1" class=""/>

<bean id="bean2" class=""/>

<!-- 引用bean -->

<bean id="bean3" class="" ref="bean1">

或者 bean3 依赖两个bean3和bean4

<bean id="bean3" class="">

 <property name="bean3Impl" ref="bean3"/>

 <property name="bean4Impl" ref="bean4"/>

</bean>

<!-- 公共属性的bean-->

<bean id="bean4" class="" abstract="true">

 <property name="name" value="chen"/>

 <property name="password" value="123"/>

</bean>

<bean id="bean5" class="" parent="bean4">

 <property name="age" value="98"/>

</bean>

<!-- array,list,set-->

<bean id="bean6" class="">

  <list>

   <value>123</value>

   <value>345</value>

  </list>

</bean>

<!-- map -->

<bean id="bean7" class="">

 <map>

  <entry key="key1" value="value1"/>

  <entry key="key2" value="value2"/>

 </map>

</bean>

</beans>

BeanFactory 加载applicationContext.xml并且从IOC容器得到bean

import org.springframework.beans.factory.BeanFactory;

import org.springframework.context.support.ClassPathXmlApplicationContext;

BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");

  UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");

  userManager.save();

七:spring 的作用域

在默认情况下,如果多次调用bean,他们是相等的。它的作用域是singleton,如果把它设置为prototype,每次调用getBean()会产生不同的对象,它们是不等的。

<bean id="" class="" abstract="true" scope="prototype"

八:spring 的装配方式

(1) byName

   如果一个bean 引用了多个bean配置文件如下

   如:bean1引用了bean2 bean3 bean4

  <bean id="bean1" class="">

   <property name="bean2" ref="bean1"/>

  <property name="bean3" ref="bean2"/>

   <property name="bean4" ref="bean3"/>

  </bean>

  如果通过byName(在配置文件beans头部加上<beans default-autowire="byName") 去自动装配,则可以大大简化配置文件

 <bean id="bean1" class=""/>这样,在Bean1中包含bean2  bean3 bean4 属性并且有setBean2() setBean3() setBean4()方法,spring会自动查找名字为bean2  bean3 bean4

  的bean的定义,并且自动装配上。

(2) byType

  就是bean在引用多个bean的时候自动根据类型去查找,而忽视了名字。(在配置文件beans头部加上<beans default-autowire="byType")

 如 bean1 有三个属性

  private Bean2 bean2  属于cn.com.chenlly.Bean2

  private Bean3 bean3  属于cn.com.chenlly.Bean3

  private Bean4 bean4  属于cn.com.chenlly.Bean4

而在配置文件中,因为class=""已经指定了所属类。所以自动会根据class类型去装配,而忽视了名字,所以id="bean2" 或者id="bean22" 都无关紧要。ioc容器都会把他们查找到的。

 <bean id="bean2"   class="cn.com.chenlly.Bean2"/>

 <bean id="bean3"   class="cn.com.chenlly.Bean3"/>

 <bean id="bean4"   class="cn.com.chenlly.Bean4"/>

九:AOP 静态代理和动态代理

 声明式服务能力

 proxy 可以控制原对象,但不能修改原对象。代理类必须和原来的接口(目标类)是一样的不能改变的

 典型的横切逻辑应用:比如在调用原对象之前进行安全性检查。

 代理模式有两种:静态代理和动态代理。动态代理即AOP思想。下面给出静态代理的例子

UserManager 接口:

public interface UserManager{

 public void addUser(String name,String passwrod);

 public void deleteUser(int id);

 public void modifyUsr(int id);

}

UserManagerImpl 类(目标类)

public class UserManagerImpl implements UserManager{

 public void addUser(String name,String passwrod){

  //todo something

 }

 public void deleteUser(int id){

  //todo something

 }

 public void modifyUsr(int id){

  //todo something

 }

}

UserManagerProxyImpl 代理类

public class UserManagerProxyImpl implements UserManager{

 private UserManagerImpl userManagerImpl;

 public UserManagerProxyImpl(UserManagerImpl userManagerImpl){

  this.userManagerImpl=userManagerImpl;

 }

 //必须和目标类有一样的实现

 public void addUser(String name,String passwrod){

  (1)安全性检查

  this.checkSecurity();

                (2)增加姓名

  this.userManagerImpl.addUser(name,password);

 }

 public void deleteUser(int id){

  (1)安全性检查

  this.checkSecurity();

                (2)删除用户

  this.userManagerImpl.deleteUser(id);

 }

 public void modifyUsr(int id){

  (1)安全性检查

  this.checkSecurity();

                (2)修改用户

  this.userManagerImpl.modifyUser(id);

 }

 //安全性检查

 private void checkSecurity(){

  //todo something

 }

}

这样只要客户端做增加,删除,修改都会增加一个安全性检查的功能。但是静态代理有个缺点就是检验安全性方法遍布整个代理类当中。所以引入了动态代理的思想

把连接点放在一个类里(模块化),当在运行期的时候,把这个方法自动切入。

下面给出动态代理的例子

把要进行安全性检查的方一个法模块化,写在类里。当我们生产了代理对象的时候,如果调用代理方法的时候,

会自动默认调用invoke方法。这个模块化的类就是所谓的切面(Aspect),安全性检查就是advice,

import java.lang.reflect.InvocationHandler;//是代理实例的调用处理程序 实现的接口。

import java.lang.reflect.Proxy;//

public class SecurityHandler implements InvocationHandler{

 private Object targetObject;//目标实例

 public Object newProxy(Object targetObject){

  this.targetObject = targetObject;

  //返回一个目标对象的代理类

  return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),//目标程序的类加载器

                                targetObject.getClass().interfaces(),//目标程序的接口

           this);//代理指定调用的处理程序

 }

 public Object invoke(Object proxy,Method method,Object args) throws Throws{

  //安全性检查,这是一个before Advice

  checkSecurity();

  //调用目标对象的正是实现,有可能有返回值,

               Object res = null;

        try{

   res = method.invoke(targetObject,args);

        }catch(Exception ex){

  ex.printStackTrace();

        }

 }

 //安全性检查

 private void checkSecurity(){

  //todo something;

 }

}

//客户端调用

public class Client{

  SecurityHandler sh = new SecurityHandler();

 //得到代理类,Annotation就是使用了动态代理机制

 UserManagerImpl userManagerImpl = (UserManagerImpl)sh.newProxy(new UserManagerImpl());

        userManagerImpl.addUser();

 userManagerImpl.deleteUser(12);

}

十:Spring和Hibernate 的事务集成

Spring 配置文件

<!-- 配置SessionFactory-->

<bean id="sessionFactory" class="org.springframwork.orm.hibernate3.LocalSessionFactoryBean">

 <property name="configLocal">

  <value> classpath:/hibernate.cfg.xml</value>

 </property>

</bean>

<!--配置事务管理器-->

<bean id="sessionManager" class="org.spring.orm.hibernate3.HibernateTransactionManager"

 <property name="sessionFactory" ref="sessionFactory">

</bean>

<!--配置事务的传播性-->

 <bean id="baseTxService"

  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"

  abstract="true">

  <property name="transactionManager" ref="transactionManager" />

  <property name="proxyTargetClass" value="true" />

  <property name="transactionAttributes">

   <props>

    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop><!-- 只读事务-->

    <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>

    <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>

    <prop key="show*">PROPAGATION_REQUIRED,readOnly</prop>

    <prop key="save*">PROPAGATION_REQUIRED</prop>

    <prop key="update*">PROPAGATION_REQUIRED</prop>

    <prop key="remove*">PROPAGATION_REQUIRED</prop>

    <prop key="delete*">PROPAGATION_REQUIRED</prop>

    <prop key="execute">PROPAGATION_REQUIRED</prop>

   </props>

  </property>

 </bean>

 在service 层加事务

 <bean id="contractManagerimpl" parent="baseTxService">

  <property name="target">

   <bean class="com.ngtc.contract.service.impl.ContractManagerImpl" autowire="byName"></bean>

  </property>

 </bean>

十一、spring 和 Struts 的集成。

 Struts 的Action 通过请求path来找type定义的Action,如果没有就创建,如果有从map里取。

 通过Spring集成的Struts Action是通过ActionProxy来拿到BeanFactory 和从IOC容器中取的

 type里对于的Action,不过在配置Action的配置文件是,name="/xxx" 必须和struts里的path

 必须一样。如

 struts配置文件

 <action path="/login"

         type="org.springframework.web.struts.DelegationActionProxy"//是一个代理Action 主要是取的BeanFactory,然后根据<action>中的path属性值到IOC容器中去得到本次请求对应的Action

         name="loginForm"

         scope="request

         >

         <forward name="success" path="/success.jsp">

  </acton>

 spring 配置文件

 <bean name="/login" class="cn.com.chenlly.LoginAction">

  <property name="" ref="">//注入业务逻辑对象

 </bean>

继续阅读