Spring总结

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.jar

spring-context-3.2.14.RELEASE.jar

spring-core-3.2.14.RELEASE.jar

spring-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-arg

constructor-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_info
USER = root
PASSWORD = root
DRIVER = 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、注入SessionFactory

2、通过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,需要注入sessionFaciory

2、使用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=thread

2、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事物管理器:需要注入SessionFactory

2、开启事物注解

3、在业务层(Service)加@Transactional注解
spring和hibernate结合总结
1、db.propreties---->c3p0 DataSource--->SessionFactory------>Dao

2、开启AOP事务:SessionFactory----->TransactionManager

3、dao---->service--->controller

编程技巧:

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

如:
ConboPooledDataSource
HibernateTransactionManager
LocalSessionFactoryBean
OpenSessionView

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

Spring和struts结合

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

Spring和Mybatis结合

优化Mybatis开发

SpringMVC,是Struts的替换者

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值