Spring框架学习笔记--更新中(SSM第一部分) 从介绍Spring以及理解实现方法到Spring核心知识 教你上手使用Spring(适合收藏)

Srping

一个轻量级java开发框架,为解决应用开发的业务逻辑层和其他层耦合问题,full-stack一站式框架专注于应用程序的开发

Spring不取代框架,而是把他们无缝连接
新的编程思想

  • IOC反转:由我们自己执行反转给Spring帮我们执行
  • IOC控制:由Spring帮我们创建、掌控对象周期,在我们需要的时候向Spring申请即可
  • DI:依赖注入

DI依赖注入

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  •   谁依赖于谁:当然是应用程序依赖于IoC容器;
  •   为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
  •   谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
  •   注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

ApplicationContext接口

每次容器启动时就会创建容器中配置的所有对象,除此之外,还提供了更多丰富的功能。
典型的实现类:

  • 从类路径下加载配置文件(常用):ClassPathXmlApplicationContext
  • 从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext

bean标签

:配置bean对象(需要容器管理的对象)

  • 通过set、构造方法、复杂类型注入给bean对象幅值,即把对象交给spring管理,value为基本类型 ref引用调用对象 type指定参数类型来调用对应的构造方法

  • name属性起一个名字,是获取bean对象的参数getbean(name)

  • class属性是一个包名,spring通过这个包名创建对象

1.set方法注入 property

    <bean name="basketball" class="com.bean.Player">
        <property name="player_name" value="kobe_bryant"/>
        <property name="player_type" value="basketball"/>
    </bean>

2.构造方法注入 constructor-arg

    <bean name="user1" class="com.bean.User">
        <constructor-arg name="u_username" value="zoufubo"/>
        <constructor-arg name="player" ref="basketball"/>
    </bean>

3.复杂类型注入(Array、List、Map、Set、Properties、Object[])

        <property name="array">
            <array>
                <value>0110</value>
                <ref bean="basketball"/>
            </array>
        </property>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <ref bean="user1"/>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="username" value="dx"></entry>
                <entry key="passwd" value="zoufubo"></entry>
                <entry key-ref="basketball" value-ref="user1"/>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="age">25</prop>
                <prop key="name">dx</prop>
            </props>
        </property>
  • 空参构造:spring创建bean对象使用空参数构造方法
    ApplicationContext配置的bean会在容器创建时全部创建出来,bean较多时,内存过大。
  • 使用延迟加载: lazy-init=”true” 创建容器时不加载对象,获取bean实例时才加载
  • scope=”singleton” 单例模式 容器只能创建一个bean对象
  • scope=”prototyped”多例,会创建新的对象 scope=”request”在web环境下,创建的对象生命周期与request请求生命周期一致
  • init-method=”user_init(init函数)”
  • destroy-method=”destroy(销毁函数)”初始化和销毁方法,分别在bean对象创建和容器关闭时调用
    <bean name="user" class="com.bean.User" lazy-init="true" scope="singleton" init-method="user_init" destroy-method="destroy">
        <property name="u_id" value="2"/>
    </bean>

Spring注解配置

需要aop包、导入约束

<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd">
       <!--把bean类作为组件扫描-->
    <context:component-scan base-package="com.bean"/>
</beans>

使用@Component注解,下面这短代码等价

@Component("user")
<bean name="user" class="com.bean.User">
  • @Controller 对应Web层
  • @Service 对应Service层
  • @Repository 对应Dao层
  • @PostConstruct()
  • @PreDestroy()**

利用注解幅值

  • @Value(value=“”)加在字段上
  • @Value(“1”)加在set上
  • @Autowired自动装配:直接在要注入的引用前加上注解@Autowired,程序会自动从容器中找同类型对象为其注入,但当对象在容器中注册多个时,无法选择注入哪个对象。
  • @Recource(name=“”)在要注入的引用前加上注解@Resource,name值为要注入的对象的名称,该对象已注入在容器中。这种注入方式是手动注入,指定注入哪一个名称的对象,常用。

单元测试与Spring整合

@Runwith(SpringJUnit4ClassRunner.class)使用junit进行测试,创建容器
@ContextConfiguration(“classpath:配置文件名”)读取配置文件

分包配置:导入其他配置文件

<import resource=””/

Spring常用约束

<?xml version="1.0" encoding="utf-8"?>

<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

</beans>

Spring AOP

面向切面的编程思想:将纵向重复的代码横向冲去解决 例如:过滤器(纵向重复的身份验证横向抽取解决)
Spring中aop:无需我们自己写动态代理的代码,容器可以管理生成动态代理对象

  • (a)Proxy动态代理:被代理的对象必须实现接口
  • (b)Cglib动态代理:被代理对象不能被final修饰

在这里插入图片描述
`在这里插入图片描述`

关于定义通知的语法:首先通知有5种类型分别如下:

  • before 目标方法执行前执行,前置通知
  • after 目标方法执行后执行,后置通知
  • after returning 目标方法返回时执行 ,后置返回通知
  • after throwing 目标方法抛出异常时执行 异常通知
  • around 在目标函数执行中执行,可控制目标函数是否执行,环绕通知
public Object around_logprint(ProceedingJoinPoint pjp){
        Object rtVaule=null;
        try {
            Object[] args=pjp.getArgs();
            rtVaule=pjp.proceed(args);
            pjp.proceed();
            return rtVaule;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        finally {
            //增强代码
            System.out.println("around记录日志");   
        }
        return rtVaule;
    }
  • public void service.UserServiceImpl.save() service包下UserServiceImpl类的无参无返回值的save()方法
  • void service.UserServiceImpl.save() service包下UserServiceImpl类的无参无返回值的save()方法
  • service.UserServiceImpl.save() service包下UserServiceImpl类的无参的save()方法
  • service.UserServiceImpl.save(..) service包下UserServiceImpl类的save()方法
  • service.UserServiceImpl.*(..) service包下UserServiceImpl类的所有方法
  • service.ServiceImpl.(..) service包下所有以ServiceImpl结尾的类的所有方法,最常用
  • service..ServiceImpl.(..) service包及其后代包下所有以ServiceImpl结尾的类的所有方法

注解配置aop需要用到的:

  • (1)扫描注解的包
  • (2)配置注解支持切面
context:component-scan base-package="com"/>
    <!--配置spring支持注解切面-->
    <aop:aspectj-autoproxy/>

Spring中的JdbcTemplate

Spring提供了一个操作数据库(CRUD)的对象JdbcTemplate(类似Dbutils)

  • spring整合JDBC的第一种方式,是将dao接口的实现类的对象放到spring容器中,这个对象依赖JDBCTemplate模板对象,所以要把JDBCTemplate模板对象放到spring容器中,再注入到实现类的对象,JDBCTemplate模板对象依赖连接池,所以要把连接池放到spring容器中,再注入到JDBCTemplate模板对象。在配置的时候要从依赖关系的最底层向上配置,所以配置的顺序依次是连接池对象、JDBCTemplate模板对象、实现类的对象。适用于xml配置

  • 第二种方式,如果dao接口的实现类先继承JdbcDaoSupport类再实现dao接口,就会根据连接池自动创建JDBC模板对象,不用手动创建JDBC模板对象,因为父类JdbcDaoSupport里面封装了创建JDBC模板的代码直接获得即可。这样在spring容器中就少一层依赖关系,dao接口实现类的对象直接依赖连接池对象。适用于注解配置

提供统一的模板方法使对数据库的操作更加方便、友好,效率也不错。但是功能还是不够强大(比如不支持级联属性)

(1)
JdbcTemplate 执行sql方法(常用之一),还有queryForObject获得单个对象,类似DButils
其中RowMapper使用BeanPropertyMapper用反射接收结果集

new BeanPropertyRowMapper<Account>() {
            public Account mapRow(ResultSet resultSet, int i){}
            }
 query(String sql, @NotNull org.springframework.jdbc.core.RowMapper<T> rowMapper,
                                   Object... args)

datasource配置数据库 jdbcTemplate配置该模板 accountDao配置接口实现类

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring?serverTimezone=GMT"/>
        <property name="password" value="52zoufubo"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="accountDao" class="com.dingxiang.dao.AccountDaoImpl">
        <property name="jt" ref="jdbcTemplate"/>
    </bean>

接口类实现

public class AccountDaoImpl implements AccountDao {
    private JdbcTemplate jt;

    public JdbcTemplate getJt() {
        return jt;
    }

    public void setJt(JdbcTemplate jt) {
        this.jt = jt;
    }

    public Account findByid(int id) {
        List<Account> list=jt.query("select * from jdbctemplatedemo where id=?",new BeanPropertyRowMapper<Account>(Account.class),id);
        return list.isEmpty()?null:list.get(0);
    }

    public Account findByname(String username) {
        List<Account> list=jt.query("select * from jdbctemplatedemo where username=?",new BeanPropertyRowMapper<Account>(Account.class),username);
        return list.isEmpty()?null:list.get(0);
    }

    public int updateAccount(Account account,String username) {
        return jt.update("update jdbctemplatedemo set username=? and money=? where username=?",account.getName(),account.getMoney(),username);
    }
}
AccountDao accountDao= (AccountDao) ac.getBean("accountDao");

Spring中的事务控制

  • (1)Spring声明式事务(基于Aop的实现):本质是对目标方法前后进行拦截,并在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

声明式事务得益于 Spring IoC容器 和 Spring AOP 机制的支持:IoC容器为声明式事务管理提供了基础设施,使得 Bean 对于 Spring 框架而言是可管理的;而由于事务管理本身就是一个典型的横切逻辑(正是 AOP 的用武之地),因此 Spring AOP 机制是声明式事务管理的直接实现者

在这里插入图片描述

事务是一个不可分割操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。

  • 1.所谓事务的隔离级别是指若干个并发的事务之间的隔离程度TransactionDefinition.ISOLATION_DEFAULT
  • 2.事务的只读属性是指,对事务性资源进行只读操作或者是读写操作
  • 3.事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务
  • 4.事务中抛出了未检查异常(继承自 RuntimeException 的异常),则默认将回滚事务。如果没有抛出任何异常,或者抛出了已检查异常,则仍然提交事务

jdbc、myabtis平台实现类:DataSourceTransactionManager

  • isolation=”DEFAULT”
  • PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
  • read-only=”false” 表示该方法可以修改数据库

xml配置事务
基于 命名空间的实现

- (1)将mybatis核心事务管理器DataSourceTransactionManager配置到spring容器,依赖连接池。
    <bean name="transaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
(2)由txAdvice切面定义事务增强处理
    <tx:advice id="txAdvice" transaction-manager="transaction">
        <tx:attributes>
            <tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
        </tx:attributes>
    </tx:advice>
(3)配置事务增强处理的切入点,以保证其被恰当的织入
    <aop:config>
        <aop:pointcut id="myadvice" expression="execution(* com.dingxiang.service.impl.IAccountServiceImpl.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myadvice"/>
    </aop:config>

注解配置事务:
基于 @Transactional 的实现
为需要加强的方法添加注解

  • @Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false)

主配置文件打开注解配置事务<tx:annotation-driven/>

Spring和Mybatis整合

(1)由DriverManagerDataSource把数据库连接交给spring管理

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring?serverTimezone=GMT"/>
        <property name="password" value="52zoufubo"/>
    </bean>

(2)SqlSessionFactoryBean

配置mybatis的SqlSessionFactory,需要注入全局配置文件和由spring管理的连接池

    <bean class="org.mybatis.spring.SqlSessionFactoryBean" name="sqlSessionFactory">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="sqlMapConfig.xml"/>
    </bean>

(3)MapperScannerConfigurer

使用一个 MapperScannerConfigurer , 它 将 会 查 找 类 路 径 下 的 映 射 器 并 自 动 将 它 们 创 建 成 MapperFactoryBean
basePackage 属性是让你为映射器接口文件设置基本的包路径。 你可以使用分号或逗号 作为分隔符设置多于一个的包路径。每个映射器将会在指定的包路径中递归地被搜索到。

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" name="configurer">
        <property name="basePackage" value="com.dingxiang.mapper"/>
    </bean>

或者可以使用MapperFactoryBean配置Mapper,通过id名获得mapper对象

        <bean id="accountMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
            <property name="mapperInterface" value="com.mapper.AccountMapper"></property>
            <property name="sqlSessionFactory" ref="sqlSessionFactoryId"></property>
        </bean>     
  • 本文作者: dzou | 微信:17856530567
  • 本文链接: http://www.dzou.top/post/c519ea2a.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!