Spring总结

来源:互联网 发布:阿迪达斯淘宝旗舰店 编辑:程序博客网 时间:2024/06/10 22:05

Spring

Spring依赖于spring工厂,管理对象创建,可以自动new对象,是个轻量级项目(轻量级:学习成本低,记东西得少-_-!)

IoC:Inverse of Controller(控制反转)

对象创建的控制权转移到程序的外部(Spring),完成解耦

DI:Dependency Injectjion 依赖注入(依赖谁就注入谁)

IoC的目的是为了解耦,对象创建的控制权转移到程序外部,需要使用对象时,通过DI来实现。

DI的两种实现方法:set注入和构造注入 另外还可以静态工厂注入

通过Spring实现IoC和DI:

1、SpringIoC 对象创建的控制权转移到  Spring容器中。2、SpringIoC容器:放各种JavaBean(Java对象的容器)/Spring bean工厂(工厂:造对象)。

使用Spring实现IoC的优势:

彻底的IoC,把对象创建的过程由硬编码改成了配置文件,进一步解耦,后期只修改配置文件即可,无需进行二次编译。

硬编码:代码中修改,硬编译,服务器需要重新部署,而配置文件则不需要


SpringIoC开发步骤:

1、加载jar包:

spring-beans-3.2.14.RELEASE.jarspring-context-3.2.14.RELEASE.jarspring-core-3.2.14.RELEASE.jarspring-expression-3.2.14.RELEASE.jar此外,Spring运行还需导入commons-logging的jar包:com.springsource.org.apache.commons.logging-1.1.1.jar其中spring-core,和spring-beans提供框架的基本组成部分,包括IOC和依赖注入功能。

2、编写Spring配置文件:

2.1、 applicationContext.xml(Spring上下文配置),一般放到src根目录,主要配置IoC和DI

①、打开页面:spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\beans.html②、在basic structure of XML-based configuration metadata中找到DTD③、复制到applicationContext.xml中
<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"></beans> <!-- 不要忘了加上beans的末标签 --><!-- xmlns的“ns”相当于struts2中的namespace-->
property标签:实现DI:默认会去调用set方法bean class:默认调用无参构造,调用有参使用constructor-argconstructor-arg:index 参数的个数、位置、类型、要和构造方法匹配

2.2、实现Spring DI

<!-- 一个bean对应一个Java对象 --><!-- name/id:对象名 --><!-- class:全限定名(包名+类名)默认调用无参构造实例化对象 --><bean name="a4" class="domain.A4"></bean><bean id="b5" class="domain.B5"></bean><bean name="colorInk" class="domain.Color"></bean><bean name="blackInk" class="domain.Black"></bean>

2.2.1、 set注入:

<bean name="printer1" class="domain.Printer">    <!-- set注入property标签:自定义引用类型对象注入使用ref,java数据类型用value进行注入 -->    <property name="ink" ref="blackInk"></property>    <property name="paper" ref="a4"></property>    <property name="brand" value="联想"></property></bean>

2.2.2、 构造注入:

<!-- index按照下标注入 --><bean name="printer2" class="domain.Printer">    <constructor-arg index="0" ref="a4"></constructor-arg>    <constructor-arg index="1" ref="colorInk"></constructor-arg></bean>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<!-- name属性按照参数名注入 --><bean name="printer2" class="domain.Printer">    <constructor-arg name="paper" ref="a4"></constructor-arg>    <constructor-arg name="ink" ref="colorInk"></constructor-arg></bean>

2.2.3、 静态工程

<!-- 通过静态工厂方法 --><bean name="printer3" class="beanfactory.PrinterFactory" factory-method="getPrinter">    <property name="ink" ref="blackInk"></property>    <property name="paper" ref="a4"></property>    <property name="brand" value="联想"></property></bean>
<!-- 通过非静态的工厂方法new对象:首先要把工厂先new出来 --><bean name="pf" class="beanfactory.PrinterFactory"></bean><!-- 使用工厂对象的intancePrinter()创建Printer对象 --><!-- factory-bean:指定使用的工厂对象名 --><bean name="printer4" factory-bean="pf" factory-method="instancePrinter">    <property name="ink" ref="blackInk"></property>    <property name="paper" ref="a4"></property>    <property name="brand" value="三星"></property></bean>
/* * 打印机工厂 */public class PrinterFactory {    //静态工厂方法    public static Printer getPrinter(){        return new Printer();    }    //实例工厂方法    public Printer instancePrinter(){        return new Printer();    }}

3、P命名空间:

3.1、 在DTD中加入xmlns:p="http://www.springframework.org/schema/p"

3.2、 使用P命名空间无须再使用property标签

<!-- 自定义引用类型后加-ref,普通类型:p:属性名 --><bean name="printer5" factory-bean="pf" factory-method="instancePrinter"      p:ink-ref="blackInk"     p:paper-ref="b5"     p:brand="佳能"></bean>

4、C命名空间:

4.1、 在DTD中加入xmlns:c="http://www.springframework.org/schema/c"

4.2、 替换constructor-arg,使用c命名空间构造器注入

<!-- 自定义引用类型后加-ref,普通类型:c:属性名 --><bean name="printer6" class="domain.Printer"     c:paper-ref="a4"     c:ink-ref="colorInk"></bean>

5、通过Spring实现各种类型的注入

/*    java基本属性类型(包括String,包装类):value    自定义应用类型:ref    Proprety:props    List集合:list    Set集合:set    Map集合:map    数组:list*/public class DIBean {    private List<String> list;    private Set<Integer> sets;    private Map<String, String> map;    private Properties prop;    private int nul;    ······    //省略Get/Set、构造方法}
<bean name="diBean" class="domain.DIBean">    <property name="list">        <list>            <value>abc</value>            <value>你好</value>        </list>    </property>    <property name="sets">        <set>            <value>12</value>            <value>14</value>        </set>    </property>    <property name="map">        <map>            <!-- map中要加entry子标签 一个entry对应一个KV -->            <entry key="" value=""></entry>            <!--key-ref表示 应用的类型 <entry key="" key-ref=""></entry> -->            <entry key="name" value="凯子"></entry>            <entry key="childrenSum" value="10"></entry>        </map>    </property>    <!-- Propeties对应.properties文件,其实就是map,key,value默认都是String类型 -->    <!-- 目的就是为了替换.properties -->    <property name="prop">        <props>            <prop key="url">jdbc:mysql://localhost:3306/XXX</prop>            <prop key="driverClass">com.mysql.jdbc.Driver</prop>            <prop key="username">xxoo</prop>            <prop key="password">xxoo</prop>        </props>    </property>    <!-- 基本注入使用value -->    <property name="nul" value="100"></property></bean>

6、测试类中获取Spring为我们创建的Bean

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

注意:

1、设值注入bean一定要有set方法,构造注入一定要有构造方法。2、jutil测试的注解:@Before作用在@Test之前

使用注解进行IoC和DI

1、applicationContext.xml中添加context命名空间,并开启扫描

<beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context"    xsi:schemaLocation="    http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans.xsd    http://www.springframework.org/schema/context     http://www.springframework.org/schema/context/spring-context.xsd">    <!-- 开启组件扫描 哪些类需要添加注解,就扫描类所在包,多个包之间用逗号分隔 -->    <context:component-scan base-package="domain"></context:component-scan>    <!-- base-package:要扫描的包(如果有其他的包可以添加逗号链接) -->    <!-- conponent:组建 --></beans>

2、Spring常用的注解

IoC注解:添加注解的类,spring会为我们创建对应对象

@Component:万能IoC注解,在需要实例化的类头上添加@Component,实例化默认的对象名是类名首字母小写,@Component("对象名"),相当于bean name例:Printer--------printer

@Component的三个子类:

@Repository:dao层类@Service:service层@Controller:控制层

DI注解:

spring官方DI注解:

@Autowired:默认按照类型查找,查找到该类型对象,自动注入该对象@Quarfer("对象名"):按照对象名去查询对象,找到自动注入@Autowired和@Quarifer结合使用

JDK DI注解:

@Resource:默认按照名字进行查找@Resource:默认去找名字为service对象,找不到再按照类型查找private UserService service;@Resource(name=“对象名”):按照指定名字进行查找

总结:

IoC注解添加到类头上:new 对象DI注解添加到属性上:实现注入使用注解无需在使用 set方法

易错点:

1、在一个配置文件中不能定义重名的对象2、注解也不允许有同名的对象、不能注入同名的对象3、在springIoC容器中可以有两个或多个类型相同的对象,但注入的时候一定按照名称注入,不能按类型注入(配置文件中不能定义重名的对象)4、对普通类型的注入用:@Value("值")

使用注解为什么可以不添加set或构造方法?

因为使用注解实现DI,靠的是反射机制,通过反射得到Field,然后打开该filed的访问权限(filed.setAccessible(true)),最后通过调用filed.set(Object,value)实现注入。

为什么要使用Spring对各种框架进行整合?

1、使大量业务类的对象交由Spring实例化和DI,统一了对Bean的管理、也就是使用SpringIoC和DI实现和其他的框架的结合2、同时Spring优化了一些框架的开发,比如Spring对Hibernate操作进行了封装(HibernateTemplate),简化了代码。3、通过SpringAOP可以进一步对业务代码和非核心代码进行解耦,比如事物操作。

SpringAOP:

AOP:AspectOrientedPrograming(面向切面编程)Aspect:切面

根本作用是为了解耦,在不修改原业务代码的基础上增加功能通用功能(所有表都需要事物管理)。AOP是个动态过程,一般情况下,非核心业务使用AOP:事务管理,日志记录

Spring和hibernante结合

Spring整合Hibernate,主要做两件事:提供事务级session和声明式的事务控制。

1、不保留hibernate的cfg.xml,把hibernate的配置声明到spring的配置文件中

2、保留hibernate cfg.xml(无需掌握);

Spring优化Hibernate步骤:

1、加载jar包:

c3p0-->mysql-connection-->hibernate Required-->SpringIoC基本包---->SpringAOP基本包log4j下slf4j两个静态日志包-->spring整合事务

2、

1、加载db.properties

db.properties# .properties是一种存储数据的配置文件# db.properties是存数据库的配置文件# .properties是key-value的结构的,而且KV默认都是String类型# 使用配置文件的目的是为了解耦,后期需要修改数据配置信息无需再修改代码URL= jdbc:mysql://127.0.0.1:3306/user_infoUSER = rootPASSWORD = rootDRIVER = com.mysql.jdbc.Driver
applicationContext.xml<!-- Spring加载.properties文件 --> <context:property-placeholder location="classpath:db.properties"/>

2、配置C3P0数据源

<!-- 使用数据库连接池的时候首先在dataSource里注入数据库连接参数 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">    <property name="driverClass" value="${DRIVER}"></property>    <property name="jdbcUrl" value="${URL}"></property>    <property name="user" value="${USER}"></property>    <property name="password" value="${PASSWORD}"></property></bean>

3、创建 SessionFactory : LocalSessionFactoryBean

创建的同时注入C3P0数据源dataSource、hibernate配置参数hibernateProperties,并且将使用注解的包进行扫描开启packagesToScan

<!-- LocalSessionFactoryBean:封装了hibernate.current_session_context_class=thread(进行了Session和线程的绑定)--><bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"></bean>

3.1、 注入c3p0数据源

<!-- 注入c3p0数据源 --><property name="dataSource" ref="dataSource"></property>

3.2、 Spring中配置Hibernate

<!-- hibernateProperties:hibernate的配置信息 --><property name="hibernateProperties">    <!-- java.util.Prperties的注入可以简化为value -->    <value>        hibernate.dialect=org.hibernate.dialect.MySQLDialect        hibernate.show_sql=true        hibernate.format_sql=true        hibernate.hbm2ddl.auto=update    </value></property>

3.3、 开启注解

<!-- 使用hibernate注解需要开启包扫描 --><!-- packagesToScan:String[] 给数组注入值使用list --><property name="packagesToScan">    <list>        <value>需要扫描的包名</value>    </list></property>

3.4、 配置映射文件的包路径 如果不想配置映射文件直接省去即可

<!-- 配置映射文件的包路径 --><property name="mappingDirectoryLocations">    <list>        <value>com/lanou/domain</value>    </list></property>

4、DAO层类中使用HibernateDaoSupport注入SessionFactory的方式

主要用来获取session

如何获取Hibernate原生Session?

1、注入SessionFactory2、通过SessiongFactory获取session

4.1、注解的方式

①、Dao层继承HibernateDaoSupport②、使用set注入SessionFactory得到HibernateTemplate (可以把HibernateTemplate近似的理解为Hibernate.Session)如:向数据库添加数据 getHibernateTemplate().save(user); 替换 session.save(user);

@Autowired不仅可以写在属性上,实现对属性的注入,还可以写在set方法上,实现set注入

@Autowired@Qualifier("sessionFactory1")private void setSuperSessionFactory(SessionFactory sessionFactory){    super.setSessionFactory(sessionFactory);}

4.2、配置文件声明的方式(使用配置文件无需写setSuperSessionFactory方法)

不继承hibernateDaoSupport使用HibernateTemplate:

1、SpringIoC实例化HibernateTemplat,需要注入sessionFaciory2、使用HibernateTemplate做Dao的成员变量,使用DI注入HibernaeTemplate实例注意:①、使用Set注入(property) 一定要有set();②、 类的版本要一致,建议使用Hibernate5
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">    <property name="sessionFactory" ref="sessionFactory"/></bean><bean id="userDao" class="dao.impl.UserDaoImpl" scope="prototype">    <property name="hibernateTemplate" ref="hibernateTemplate"/></bean>

注意:

springIoC实例化的对象默认是单例的:singleton 通过scope来配置Bean的模式

scop常见值:

singleton(单例)prototype(每次使用都会创建一个新的实例)request(把该对象添加到reuqest请求对象中request.setAttribute("beanName", bean))session(session.setAttribute("beanName", bean))
//使用HibernateTemplate做dao的成员变量,后期springDI//HibernateTemplate是线程安全的,其底层封装了currentSession(也就是和线程绑定的session)private HibernateTemplate hibernateTemplate;//使用set注入(property)一定要有set()public HibernateTemplate getHibernateTemplate() {    return hibernateTemplate;}public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {    this.hibernateTemplate = hibernateTemplate;}//不用get/set,就用注释进行注入

**4.3、**Hibernate中 getCurrentSession()和openSession()的区别:

1、getCurrentSession是线程安全的,底层还是OpenSession,他需要开启事务,在事务提交的时候会自动关闭session,所以不能session.close();不要忘了配置:hibernate.current_session_context_class=thread2、openSession:线程非安全,一个CRUD对应一个open close,查询无须开启事务

4.3.1、 getCurrentSession() 方法获取session

public my_user findUser(my_user user) throws UserNotFoundException {    Session session = sessionFactory.getCurrentSession();    Transaction tx = session.beginTransaction(); // 开启事务    Query query = session.createQuery("from user_info where name=:name and password=:pwd");    query.setParameter("user_name", user.getUser_name());    query.setParameter("user_password", user.getUser_password());    my_user returnUser = (my_user) query.uniqueResult();    tx.commit(); // 提交事务    if(returnUser==null){        throw new UserNotFoundException("该用户不存在");    }    return returnUser;}//如果配置了 hibernate.current_session_context_class=thread 那么必须进行编程式事务管理//此段代码已经进行了编程式事务管理,所以需要在applicationContext.xml中配置

4.3.2、 openSession() 方法获取session

public my_user findUser(my_user user) throws UserNotFoundException {    Session session = sessionFactory.openSession();    Query query = session.createQuery("from user_info where name=:name and password=:pwd");    query.setParameter("name", user.getName());    query.setParameter("pwd", user.getPassword());    user_info returnUser = (user_info) query.uniqueResult();    session.close();  //一个CRUD对应一个open close    if(returnUser == null){        throw new UserNotFoundException("该用户不存在");    }    return returnUser;}

5、通过调用HibernateTemplate的API实现CRUD

hibernateTemplate的常用方法:

void delete(Object entity):删除指定持久化实例deleteAll(Collection entities):删除集合内全部持久化类实例find(String queryString):根据HQL查询字符串来返回实例集合findByNamedQuery(String queryName):根据命名查询返回实例集合findByExample:会对查询自动添加where条件,查询参数封装到user里get(Class entityClass, Serializable id):根据主键加载特定持久化类的实例save(Object entity):保存新的实例saveOrUpdate(Object entity):根据实例状态,选择保存或者更新update(Object entity):更新实例的状态,要求entity是持久状态setMaxResults(int maxResults):设置分页的大小

注意:

HIbernateTemplate.find( )方法返回list<?>,即find( )方法的返回值都是list

HibernateTemplate建议使用find(), find就是Hibernate.Query的封装
find(hql):List<?>
find(hql, Object...params):带查询条件的

6、使用SpringAOP进行事务管理

日后数据库事务管理一般交由spring处理,spring通过AOP的方法实现无侵入式事务。

<!-- 声明spring事务管理器:需要注入sessionFactory --><!-- 把SessionFactory交由了transactionManager管理,这样我们无须在关注事务 --><bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">    <property name="sessionFactory" ref="sessionFactory"></property></bean><!-- 开启事务注解 --><tx:annotation-driven transaction-manager="transactionManager"/>

基于注解的Spring事务管理

1、初始化Spring事物管理器:需要注入SessionFactory2、开启事物注解3、在业务层(Service)加@Transactional注解

spring和hibernate结合总结

1、db.propreties---->c3p0 DataSource--->SessionFactory------>Dao2、开启AOP事务:SessionFactory----->TransactionManager3、dao---->service--->controller

编程技巧:

如和获取一些常见类的全限定名?

如:
ConboPooledDataSource
HibernateTransactionManager
LocalSessionFactoryBean
OpenSessionView

使用快捷键:ctrl+shift+T(如果没反应,可能是热键冲突,比如qq的快捷键),可以找到该类的全限定名。

Spring和struts结合

优化Strurs开发(可以被替换)

Spring和Mybatis结合

优化Mybatis开发

SpringMVC,是Struts的替换者

原创粉丝点击