Spring小结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mada26/article/details/70037070

1:@Autowired与@Resource比较

1:@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。2:@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:

@Autowired()@Qualifier("baseDao") private BaseDao baseDao;

3:@Resource(这个注解属于J2EE的),默认安照名称进行装配,名称可以通过name属性进行指定,

如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

@Resource(name="baseDao")  private BaseDao baseDao;

@Resource可以注解在字段上,且这个注解是属于J2EE的,减少了与spring的耦合。


Spring的IOC和AOP:
IoC(Inversion of Control):IoC就是应用本身不依赖对象的创建和维护而是交给外部容器(这里为spring),
这要就把应用和对象之间解耦,控制权交给了外部容器。即Don't call me ,I'll call you!
所以IoC也称DI(依赖注入)对象的创建和维护依赖于外部容器.

(Aspect Oriented Programming):面向切面编程。就是把一些贯穿在各个模块之间相同的功能抽象出来,然后封装成一个面。
AOP一般都是通过代理来实现,利用代理就有目标对象是什么,拦截哪些点(方法),拦截后要做什么。
JoinPoint(连接点):被拦截到的点. Advice(通知):拦截JoinPoint之前与之后要做的事。
PointCut(切入点):对joinPoint进行拦截的定义。Target(目标对象):代理的目标对象。
对于异常处理,日志功能,权限的检查,事务等都是贯穿到各个模块之中,因此进行AOP.
代理技术有面向接口和生成子类.


1.什么是Spring,有什么作用

  Spring框架属于整合框架。可以将Struts,Hibernate等技术整合在一起使用。
好处是可以降低组件之间耦合度,有利于程序的扩展和升级。
   Spring框架主要具有以下几点功能:
 --Spring框架提供了与其他技术整合的API   (整合API可以引用原Struts,Hibernate功能,使用更简洁)
 --Spring框架提供了一个容器,该容器可以创建和管理程序中的组件对象(Spring核心)
 --Spring框架容器提供了 IOC特性(可以降低两个组件对象的耦合度)
 --Spring框架容器提供了 AOP特性(可以将事务等共通功能以低耦合方式作用到原功能组件上)


2.Spring基本使用
   *1)Spring容器的基本(核心)使用可以创建和管理组件对象。
     使用步骤:
      --引入spring核心开发包
      --添加spring配置文件
      --将程序组件定义到spring配置文件中
      --获取spring容器对象,从容器中获取Bean组件对象。
    2)Spring容器对Bean的管理     
     *a.控制Bean对象创建模式
在<bean>元素中,利用scope属性可以指定Bean组件创建对象的方式
 prototype:非单例模式 singleton:  单例模式(默认)  scope="prototype/singleton"
以后,在Web程序中,通过一些配置,可以扩展出request,session等属性值.
     b.可以控制单例模式的创建时机
singleton模式的Bean组件,默认是在ApplicationContext容器实例化时创建出来。
prototype模式是在调用ac.getBean()方法时创建。
  可以在<bean>元素中使用lazy-init="true",将singleton模式对象创建工作推迟到
     getBean()方法调用时刻。
     c.可以指定Bean对象初始化和销毁方法
<bean init-method="初始化方法" destroy-method="销毁方法">
当Spring将Bean对象创建完毕后,会自动调用init-method指定的方法。
destroy-method指定的方法需要满足下面条件才能执行:
--scope="singleton"才能使用
--执行AbstractApplicationContext容器的close()方法触发。
   
2)Spring框架的IOC特性
IOC解决的问题:可以降低两个组件对象之间关联,降低耦合度.
  a.IOC Inverse of Controller被称为控制反转或反向控制。(更确切的理解应该是控制转移)
控制:指的是组件对象创建,初始化,销毁以及关系指定等逻辑。  
将上述控制逻辑由第三方容器或框架(Spring)负责,从而被称为IoC。
当遇到组件的替换或功能扩展时,只需要修改Spring配置,相关联组件不需要修改。
(降低耦合度)
  b.DI Dependency Injection称为依赖注入
依赖注入是Spring实现IoC的技术途径。
依赖注入 主要分为set方式注入和构造方法注入.
  
   (推荐)set方式注入的使用步骤:
   --在Action中定义dao接口变量及其set方法
   --在Spring配置Action组件的<bean>元素中,使用下面格式:
     <property name="属性名"     ref="要注入的Bean对象id值"> </property>  


    构造方式注入的使用步骤:
   --在Action中定义dao的接口变量,以及带参数的构造方法。
   --在Spring配置Action组件的<bean>元素中,使用下面格式:
     <construtor-arg  index="指定参数索引,从0开始">    
ref="要注入的Bean对象的id值"
     </construtor-arg>


3.各种类型信息的注入
   *1)注入Bean对象
     <property name="属性名" ref="">
   2)注入基本类型 注入数值或字符串类型值
    <property name="属性名" value="值">
   3)注入集合类型 注入List集合配置方法
   <property> 
      <list>
         <value>值</value>
         ...
      </list>
   </property>
  
    注入Set集合配置方法
   <property> 
      <set>
         <value>值</value>
         ...
      </set>
   </property>


    注入map集合类型
    <property>
        <map>
          <entry key="" value="">
          </entry>
          ......
        </map>
    </property>
    注入Properties类型
    <property>
       <props>
         <prop key="">值</prop>
         ......
       </props>
    </property>


=====================
1.Spring框架在SSH中作用
*2.掌握Spring容器对Bean的管理

*3.掌握Spring容器IOC的使用

4.各种类型数据的注入


AOP及其作用

Aspect Oriented Programming(面向方面编程)     Object Oriented Programming(面向对象编程)
AOP是以OOP为基础,用于改善程序组件对象之间的结构,降低耦合度。
AOP是以方面组件为关注点,方面组件是用于封装共通处理逻辑的,将来可以被其它的目标组件调用。
AOP主要是解决共通处理与目标组件之间解耦
2:AOP的基本使用
 --引入ioc和aop开发包
 --找出共通处理,写成一个Bean组件
 --在Spring配置中定义AOP,将共通处理组件定义成一个<bean>
定义<aop:pointcut>,指定哪些组件为目标,
定义<aop:aspect>,将共通组件定义成方面,
定义<aop:before>,指定目标和方面作用的时机.
3.AOP相关的概念
 *1)方面(Aspect):方面Aspect封装了共通处理,可以切入到其它目标组件方法上。
 *2)切入点(Pointcut):指定方面组件可以作用到哪些目标组件上。
指定方面组件可以利用一个特殊表达式指定。within(类型)

<!-- 利用Spring的AOP将CheckRoleBean作用到各个Action的execute方法 -->
<bean id="checkRoleBean" class="org.tarena.aop.CheckRoleBean"></bean>
<aop:config>
<!-- 切入点:指定方面组件可以作用到哪些目标组件上 -->
<aop:pointcut id="actionPoint" expression="within(org.tarena.action.*)"></aop:pointcut>
<!-- 方面:指定哪个组件为方面组件 ,封装了共通处理-->
<aop:aspect id="checkRoleAspect" ref="checkRoleBean">
<!-- 指定checkRoleBean组件处理和Action组件方法作用的时机 -->
<aop:before pointcut-ref="actionPoint" method="check" />
</aop:aspect>
</aop:config>

 *3)通知(Advice):用于指定方面和目标之间的作用时机。
通知类型如下:                        
 前置通知:先执行方面,再执行目标。
 后置通知:先执行目标,目标方法没抛出异常,再执行方面。
 最终通知:先执行目标,目标有无异常都执行方面。
 环绕通知:先执行方面前半部分,再执行目标,再执行方面后半部分。
 异常通知:先执行目标,发生异常后再执行方面。


   try{
     //执行方面--前置通知<aop:before>
     //执行方面--环绕通知<aop:around>
    执行目标组件处理
     //执行方面--环绕通知<aop:around>
     //执行方面--后置通知<aop:afterReturning>
   }catch(){
     //执行方面--异常通知<aop:afterThrowing>
   }finally{
     //执行方面--最终通知<aop:after>
   }

public String intercept(ActionInvocation ai){
//前半部分
ai.invoke();//执行action
//后半部分
}
  4)连接点(JoinPoint):切入点是连接点的集合。
  指的是方面和某一个目标的某一个方法的作用点。利用该对象可以获取方面和目标方法作用的信息,
例如目标方法名,目标组件类型等。
  5)目标组件(Target):切入点指定的目标组件。将来调用方面的组件。
  6)动态代理技术(AutoProxy)
  当目标组件使用了AOP切入方面组件后,ac.getBean("")方法返回的类型是采用动态代理技术生成的一个新类型。
当使用代理对象执行业务方法时,代理对象会调用方面和原目标对象的处理方法。 


   Spring框架提供了两种代理技术的实现。
   1:CGLIB技术:适用于没有接口的目标组件。
public class 代理类型 extends 目标类型{
   //重写目标Action的execute
   public String execute(){
      //调用方面组件
      //调用目标组件super.execute();
   }
}
//利用父类变量接收代理类对象
AddCostAction action = (AddCostAction)ac.getBean("addCostAction");
action.execute();//调用代理对象的execute
   2:JDK Proxy API技术:仅适用于有接口的目标组件。
public class 代理类型 implements 目标接口{
}
//利用接口变量接收代理类对象
ICostDao dao = (ICostDao)ac.getBean("jdbcCostDao");
dao.save();//调用代理类型的save()方法
4.切入点的使用
  切入点表达式可以指定目标组件及其方法。表达式写法如下:
  *1)方法限定表达式 可以指定哪些方法当目标启用方面功能。
execution (修饰符? 返回类型  方法名(参数列表) throws异常类型?)
示例1:匹配方法名以find开头的Bean对象
 execution (* find*(..))
示例2:匹配JdbcCostDao中的save方法
 execution (* org.dao.JdbcCostDao.save(..))
示例3:匹配org.dao包下所有类的所有方法
 execution (* org.dao.*.*(..))
示例4:匹配org.dao包及其子包下所有类所有方法
 execution (* org.dao..*.*(..))

  *2)类型限定表达式 可以指定哪个组件的所有方法都启用方面功能。
  within(类型)
 示例1:匹配AddCostAction中所有方法
   within(org.action.AddCostAction)
 示例2:匹配org.action包下所有类所有方法
   within(org.action.*)
 示例3:匹配org.action包及其子包所有类所有方法
   within(org.action..*)
  3)Bean组件id或name限定表达式 bean("id或name属性值")
    提示:id和name都用于指定Bean组件的标识符,但是id更严格,不允许使用/等特殊字符,
           但是name允许的。
 示例1:匹配<bean>元素id或name属性为jdbcCostDao组件的所有方法bean("jdbcCostDao")
 示例2:匹配<bean>元素id或name属性以Action结尾的组件的所有方法bean(*Action)
  4)方法参数限定表达式 args(参数列表)
  示例:匹配只有一个参数的,类型为String的方法args(java.lang.String)


 提示:上述表达可以利用&&,||进行拼接。 例如within(org.action..*) && !execution(...)


5.AOP编程 按以下步骤
  1)找出共通处理,写成方面组件,
  2)找出目标组件,写成切入点表达式,
  3)找出通知类型,使用相应通知切入.


 案例1:记录用户执行操作的信息
    1)方面组件 可以根据用户操作记录日志信息
    2)目标组件(Action,因为一个Action方法代表一个完整的请求处理) 写成切入点within
    3)方面组件功能在目标方法之后执行,由于需要使用连接点获取类名和方法,因此
使用环绕(传入连接点信息)
   public Object xxx(ProceedingJoinPoint pjp)


  案例2:将程序中抛出的异常信息记录下来
    1)方面组件 记录异常信息
    2)目标组件 Action组件
    3)在Action发生异常之后执行方面组件 异常通知
     public void xxx(异常类型参数){}


Spring框架管理Bean组件

Spring框架IoC机制实现Bean之间调用
Spring框架AoP机制实现共通Bean与目标Bean之间的调用


1.Spring中的注解配置:
从JDK5.0开始,提供了注解,泛型,新for循环,自动拆装箱等技术。
目前框架利用注解代替XML配置内容。
注解是一种标记(@标记),可以写在类定义前,方法定义前,属性变量定义前。
    1)组件自动扫描技术
   可以指定一个包路径,可以自动的扫面该包及其子包下的所有Class组件,当发现Class中有
指定的注解标记,会转化成原XML配置中的<bean>定义。
   使用方法如下:
----在Spring的主配置文件中开启组件自动扫描
--<context:component-scan base-package="包路径"/>
----在需要扫描进入Spring容器的Class中,在类定义前使用下面注解标记之一:
(用其中一种也可,只是为了分层开发而定义了以下多个标记)
@Controller 控制层:Action组件
@Service 业务逻辑层:业务组件
@Repository 持久层:DAO组件
@Component:其他组件

---如果需要注入Bean对象,在属性变量或者set方法前使用下面标记
@Resource:注入注解标记
@Autowired上面标记是按类型匹配注入。 Consolas字体
如果需要指定名称注入可以使用
@Resource(name="指定id值")或者@Autowired@Qualifier("指定id值")


  2)AOP注解配置 使用方法如下:
  --在Spring的主配置中开启AOP注解配置<aop:aspectj-autoproxy />
  --编写方面组件,在组件中使用下面注解标记
    @Component//先将Bean扫描到Spring容器
    @Aspect//将Bean指定为方面组件
//通知标记
    @Before   //前置通知
    @After    //最终通知
    @AfterReturning //后置通知
    @AfterThrowing  //异常通知
    @Around  //环绕通知


  3)选择XML还是注解
  --注解方式简单,快捷,不便于维护和修改.
  --xml方式可读性强,复杂,便于维护和修改


Spring整合应用

1.Spring对数据库访问技术的支持
  --提供了整合的API
   DaoSupport组件:编写DAO的基类,提供了一些DAO需要的方法。
JdbcDaoSupport,HibernateDaoSupport
    Template组件: 封装了增删改查操作方法
JdbcTemplate,HibernateTemplate
  --提供了一致的异常处理层次
将各种数据库访问技术异常类型统一成了DataAccessException,在业务处理时,对该异常进行捕获处理即可。
  --提供了声明式事务管理方法 基于AOP机制,只需要添加配置就可以完成事务的控制。


2.Spring对JDBC技术整合应用
  整合开发步骤:
  --引入开发包和配置:spring开发包;数据库驱动;连接池开发包
spring的配置文件
  --定义实体类和Dao接口,根据COST表编写一个Cost类;定义了一个ICostDao接口
  --根据Dao接口编写JDBC实现类,实现类需要继承JdbcDaoSupport,利用DaoSupport提供的Template
完成增删改查。
    super.getJdbcTemplate()获取Template对象,然后使用update(sql,参数数组Object[]);实现增删改操作。

增加操作的实现---------------
public void save(Cost cost) {
String sql = "insert into cost values" +
"(seq_cost.nextval,?,?,?,?,'1',?,sysdate,null,null,?)";
Object[] params = {
cost.getName(),
cost.getBaseDuration(),
cost.getBaseCost(),
cost.getUnitCost(),
cost.getDescr(),
cost.getCostType(),
};
super.getJdbcTemplate().update(sql,params);
}

更新操作的实现-------------------
public void update(Cost cost) {
String sql = "update cost set name=?,base_duration=?,base_cost=?," +
"unit_cost=?,descr=?,cost_type=? where id=?";
Object[] params = {
cost.getName(),
cost.getBaseDuration(),
cost.getBaseCost(),
cost.getUnitCost(),
cost.getDescr(),
cost.getCostType(),
cost.getId()
};
super.getJdbcTemplate().update(sql,params);
}

删除操作的实现-----------------
public void deleteById(int id) {
String sql = "delete from cost where id=?";
Object[] params = {id};
super.getJdbcTemplate().update(sql,params);
}

queryForObject():查询单行记录------------------------
public Cost findById(int id) {
String sql = "select * from cost where id=?";
Object[] params = {id};
Cost cost = (Cost)super.getJdbcTemplate().
queryForObject(sql, params,new CostMapper());
return cost;
}


query()查询多行记录------------------------------------
public List<Cost> findAll() {
String sql = "select * from cost";
@SuppressWarnings("unchecked")
List<Cost> list = super.getJdbcTemplate().query(sql, new CostMapper());
return list;
}
    
    queryForInt():查询单行单列---------------------------------------
    
    RowMapper接口组件:用于将记录转换成实体对象------------------------------------------
    public class CostMapper implements RowMapper{


public Object mapRow(ResultSet rs, int index) throws SQLException {
//ResultSet每一行记录会自动调用一次该方法,将当前ResultSet游标指向的记录封装成实体对象.
Cost c = new Cost();
c.setId(rs.getInt("id"));
c.setName(rs.getString("name"));
c.setBaseDuration(rs.getInt("BASE_DURATION"));
c.setBaseCost(rs.getDouble("BASE_COST"));
c.setUnitCost(rs.getDouble("UNIT_COST"));
c.setStatus(rs.getString("STATUS"));
c.setDescr(rs.getString("DESCR"));
c.setCreatTime(rs.getDate("CREATIME"));
c.setStartTime(rs.getDate("STARTIME"));
c.setCloseTime(rs.getDate("CLOSETIME"));
c.setCostType(rs.getString("COST_TYPE"));
return c;
}

}
        
  --将DAO组件定义到Spring容器中
  --在Spring容器中定义一个连接池Bean对象将连接池给DAO注入,为template提供连接。
  --测试,从Spring容器获取DAO对象


3.Spring+JDBC注解整合
  --在Spring的配置文件中开启组件扫描
  --在Dao组件中使用扫描注解@Repository
  --在Dao中定义一个set方法,使用@Resource将DataSource连接池注入,给daosupport传入
  --在Spring的配置文件中定义dataSource连接池
  --获取Spring容器的DAO对象,测试


1.Spring和Hibernate框架的整合应用
  整合步骤如下:
  --引入开发包 Spring开发包,Hibernate开发包,数据库驱动包,连接池开发包
  --根据表编写实体类和hbm.xml    如(Cost和Cost.hbm.xml)
  --编写DAO接口
  --根据DAO接口编写实现类 实现类继承HibernateDaoSupport,利用它提供的HibernateTemplate
完成增删改查操作
  --将DAO实现类定义到Spring容器中
  --定义SessionFactory,将SessionFactory给DAO注入
  --获取Spring容器的DAO对象,测试


1.Spring与Struts2整合的应用
 hello.action-->HelloAction-->MessageDao-->hello.jsp


 --添加Struts2开发框架 引入jar包,struts.xml文件,web.xml的filter配置
 --添加Spring开发框架 引入jar包,applicationContext.xml
 --*编写Action和Dao 利用Spring组件扫描,将Action和Dao扫描到Spring容器。将Dao给Action注入
 --*在struts.xml中添加Action配置
<action name="请求名"   class="Spring容器中Action组件的id">
 --*引入一个struts-spring-plugin.jar开发包  (作用:利用class值去访问Spring容器取Bean对象)
 --*在web.xml中定义Listener (作用:在启动tomcat时,实例化Spring容器对象)


2.struts-spring-plugin.jar的作用:该包由Struts2框架提供.该jar包提供了一个StrutsSpringObjectFactory组件。
Struts2中有一个ObjectFactory组件,该组件提供了buildAction(),buildBean()方法,
用于获取Action和其它组件的对象。
当引入struts-spring-plugin.jar时,会自动利用StrutsSpringObjectFactory
替代原有的Struts的ObjectFactory组件。
public class StrutsSpringObjectFactory{
   //调用此方法获取Action对象
   public Object buildAction(){
     try{
        //----获取Action的第一种途径------
        //1.获取Spring容器对象ac
        //2.从容器中获取Action对象
        Object action = ac.getBean("class属性值");
        //3.返回action对象
     }catch(){
        //----获取Action的第二种途径------
        //1.通过反射机制创建一个Action对象
        Class c = Class.forName("org.tarena.action.HelloAction");
        Object action = c.newInstance();
        //2.将Spring容器中的Bean对象给action注入.(默认是名称匹配,Bean的id值和action的属性名匹配)
        //3.返回action对象
     }
   }
}


3.基于StrutsSpringObjectFactory特点
          Struts与Spring结合可以有两种方法: 参考ssh-1.jpg和ssh-2.jpg结构图。
两种主要区别在于Action组件的位置不同。
ssh-1是交给Spring容器创建,ssh-2是交给ObjectFactory创建
使用时由<action>配置的class值决定,如果class指定的是包名.类名走ssh-2流程。
如果class指定bean的id值走ssh-1流程。

上述两种整合方法的选用(主要考虑事务控制问题):
如果Action+DAO模式,建议采用ssh-1;如果Action+Service+DAO模式,建议采用ssh-2
 
4.SSH流程中的关键环节(排错点)
 1)web.xml是否配置Struts2的Filter控制器(决定请求能够进入Struts2处理流程)
 2)struts.xml的<action name="" class="">配置
   (name决定请求是否有Action处理)
   (class决定Action由Spring创建还是由StrutsSpringObjectFactory创建。决定走ssh-1或ssh-2流程)
 3)是否引入struts-spring-pulgin.jar(决定是否能够完成Struts和Spring整合)
 4-1)如果是ssh-1流程,检查Action和DAO是否在Spring容器,
DAO是否给Action,注入Action的id值是否与<action>的class一致
 4-2)如果是ssh-2流程,检查DAO是否在Spring容器,DAO的id值是否与Action中的属性名一致
<action>的class指定的包名.类名是否正确
 5)检查web.xml是否包含Listener配置(决定Spring容器是否实例化)




5:Struts2的Filter控制器,如果是Action处理流程,不会执行chain.doFilter()代码,因此后续的Filter不会调用到.
注意::在使用中需要将其他的Filter定义到Struts2控制器之前!!!
public class MyFilter implement Filter{
  public void doFilter(request,response,chain){
     //调用下一个filter或jsp,servlet
     chain.doFilter(request,response);
  }
}


public class StrutsFilter implement Filter{
  public void doFilter(request,response,chain){
     //1.判断是否为Struts请求
     //2.如果是/login,/login.action要根据struts.xml信息获取Action,调用Interceptor,Action,Result组件处理
     //3.如果是login.jsp请求,会执行chain.doFilter(request,response)方法取调用JSP资源
  }
}


*1.使用OpenSessionInViewFilter注意事项:
  --为了支持Hibernate延迟加载操作。Spring容器中的SessionFactory必须命名为"sessionFactory"!!!
  --该Filter必须定义在Struts的Filter之前!!!
  --该Filter启用后,会将Session设置成只读模式,原有增删改操作不支持了,需要使用事务控制才能执行增删改操作!!!
*2.注解方式使用事务
  --在Spring配置中开启注解事务管理定义事务管理的方面组件(Spring提供),利用<tx:annotation-driven>开启注解配置
  --在目标组件中,类定义前或方法定义前加@Transactional
3.XML事务配置
 Spring事务管理采用AOP机制实现。提供以下两种方式:
  1)声明式事务管理(基于配置方法)
    有XML和注解两种。
  2)编程式事务管理(基于Java编程)
    利用TransactionTemplate将若干个操作封装


声明式事务:
在配置文件中将事务配置好,通过bean的形式,调用spring的事务。然后在程序中不需要太多的事务管理代码,比如事务commit,backroll等
程序式事务:
就是在程序中获得spring的事务,然后通过此事务管理对象来操作事务,比如事务提交,回滚等,也就是说程序中需要通过代码的形式来管理事务。


为什么要有事务管理?
事务都是为了保证数据的一致和完整,保证整个操作的原子性。不论是spring事务还是×××事务,都一样。
银行扣款流程的例子就不举了。
一般什么时候用?
简单的一句select就用不到事务,当然,如果你的这个select要记录日志,日志记录出错不让select,那就又是一个事务了。
还有一些,比如,上传文件。文件保存在操作系统,相关信息保存在数据库,要么两个保存都成功,要么都失败,
这么也是一个事务了。


  


猜你喜欢

转载自blog.csdn.net/mada26/article/details/70037070
今日推荐