zoukankan      html  css  js  c++  java
  • 阶段六模块二 Spring 学习笔记

    Spring概述

    Spring是什么

    Spring是分层的 Java SE/EE应用 full-stack(全栈式) 轻量级开源框架。

    提供了表现层 SpringMVC和持久层 Spring JDBC Template以及 业务层 事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。

    两大核心:以 IOC(Inverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。

    Spring优势

    1)方便解耦,简化开发
      Spring就是一个容器,可以将所有对象创建和关系维护交给Spring管理
      什么是耦合度?对象之间的关系,通常说当一个模块(对象)更改时也需要更改其他模块(对象),这就是耦合,耦合度过高会使代码的维护成本增加。要尽量解耦
    2)AOP编程的支持
      Spring提供面向切面编程,方便实现程序进行权限拦截,运行监控等功能。
    3)声明式事务的支持
      通过配置完成事务的管理,无需手动编程
    4)方便测试,降低JavaEE API的使用
      Spring对Junit4支持,可以使用注解测试
    5)方便集成各种优秀框架
      不排除各种优秀的开源框架,内部提供了对各种优秀框架的直接支持

    Spring体系结构

     IOC

    控制反转(Inverse Of Control)不是什么技术,而是一种设计思想。它的目的是指导我们设计出更加松耦合的程序。

    控制:在java中指的是对象的控制权限(创建、销毁)
    反转:指的是对象控制权由原来 由开发者在类中手动控制 反转到 由Spring容器控制

    Spring基于的开发步骤

    1. 导入坐标
    2. 创建Bean
    3. 创建applicationContext.xml
    4. 在配置文件中进行Bean配置
    5. 创建ApplicationContext对象,执行getBean

    Spring API继承体系介绍

     BeanFactory

    BeanFactory是 IOC 容器的核心接口,它定义了IOC的基本功能。

    特点:在第一次调用getBean()方法时,创建指定对象的实例

    ApplicationContext

    代表应用上下文对象,可以获得spring中IOC容器的Bean对象。

    特点:在spring容器启动时,加载并创建所有对象的实例

    常用实现类

    1. ClassPathXmlApplicationContext
       它是从类的根路径下加载配置文件 推荐使用这种。
      
    2. FileSystemXmlApplicationContext
       它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
      
    3. AnnotationConfigApplicationContext
       当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

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

    常用方法

    1. Object getBean(String name);
      根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。
    2. <T> T getBean(Class<T> requiredType);
      根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错。
    3. <T> T getBean(String name,Class<T> requiredType);
      根据Bean的id和类型获得Bean实例,解决容器中相同类型Bean有多个情况。

    Bean标签基本配置

    <bean id="" class=""></bean>
    * 用于配置对象交由Spring来创建。
    * 基本属性:
      id:Bean实例在Spring容器中的唯一标识
      class:Bean的全限定名
    * 默认情况下它调用的是类中的 无参构造函数,如果没有无参构造函数则不能创建成功。

    Bean标签范围配置

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

    scope属性指对象的作用范围,取值如下:

    1. 当scope的取值为singleton时
       Bean的实例化个数:1个
          Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
          Bean的生命周期:
            对象创建:当应用加载,创建容器时,对象就被创建了
            对象运行:只要容器在,对象一直活着
            对象销毁:当应用卸载,销毁容器时,对象就被销毁了
    2. 当scope的取值为prototype时
       Bean的实例化个数:多个
          Bean的实例化时机:当调用getBean()方法时实例化Bean
          Bean的生命周期:
             对象创建:当使用对象时,创建新的对象实例
             对象运行:只要对象在使用中,就一直活着
             对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了

    Bean生命周期配置

    <bean id="" class="" scope="" init-method="" destroy-method=""></bean>
    * init-method:指定类中的初始化方法名称
    * destroy-method:指定类中销毁方法名称

    Bean实例化三种方式

    无参构造方法实例化

    它会根据默认无参构造方法来创建类对象,如果bean中没有默认无参构造函数,将会创建失败

    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"/>

    工厂静态方法实例化

    <bean id="userDao" class="com.lagou.factory.StaticFactoryBean" factory-method="createUserDao" />

    工厂普通方法实例化

    <bean id="dynamicFactoryBean" class="com.lagou.factory.DynamicFactoryBean"/>
    <bean id="userDao" factory-bean="dynamicFactoryBean" factory-
    method="createUserDao"/>

    Bean依赖注入概述

    依赖注入 DI(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。
    在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
    那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是通过框架把持久层对象传入业务层,而不用我们自己去获取。

    Bean依赖注入方式

    构造方法

    public class UserServiceImpl implements UserService {
      private UserDao userDao;
      public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
     }
      @Override
      public void save() {
        userDao.save();
     }
    }

    配置Spring容器调用有参构造时进行注入

    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.lagou.service.impl.UserServiceImpl">
      <!--<constructor-arg index="0" type="com.lagou.dao.UserDao" ref="userDao"/>-
    ->
      <constructor-arg name="userDao" ref="userDao"/>
    </bean>

    set方法

    在UserServiceImpl中创建set方法

    public class UserServiceImpl implements UserService {
      private UserDao userDao;
      public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
     }
      @Override
      public void save() {
        userDao.save();
     }
    }

    配置Spring容器调用set方法进行注入

    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.lagou.service.impl.UserServiceImpl">
      <property name="userDao" ref="userDao"/>
    </bean>

    P命名空间注入

    P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:

    首先,需要引入P命名空间:

    xmlns:p="http://www.springframework.org/schema/p"

    其次,需要修改注入方式:

    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"/>
    <bean id="userService" class="com.lagou.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>

    Bean依赖注入的数据类型

    1. 普通数据类型

    2. 引用数据类型

    3. 集合数据类型

    注入普通数据类型

    <bean id="user" class="com.lagou.domain.User">
      <property name="username" value="jack"/>
      <property name="age" value="18"/>
    </bean>

    注入集合数据类型

    1)List集合注入

    <bean id="user" class="com.lagou.domain.User">
      <property name="username" value="jack"/>
      <property name="age" value="18"/>
    </bean>
    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl">
      <property name="list">
        <list>
          <value>aaa</value>
          <ref bean="user"></ref>
        </list>
      </property>
    </bean>

    2)Set集合注入

    <bean id="user" class="com.lagou.domain.User">
      <property name="username" value="jack"/>
      <property name="age" value="18"/>
    </bean>
    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl">
      <property name="set">
        <list>
          <value>bbb</value>
          <ref bean="user"></ref>
        </list>
      </property>
    </bean>

    3)Array数组注入

    <bean id="user" class="com.lagou.domain.User">
      <property name="username" value="jack"/>
      <property name="age" value="18"/>
    </bean>
    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl">
      <property name="array">
        <array>
          <value>ccc</value>
          <ref bean="user"></ref>
        </array>
      </property>
    </bean>

    4)Map集合注入

    <bean id="user" class="com.lagou.domain.User">
      <property name="username" value="jack"/>
      <property name="age" value="18"/>
    </bean>
    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl">
      <property name="map">
        <map>
          <entry key="k1" value="ddd"/>
          <entry key="k2" value-ref="user"></entry>
        </map>
      </property>
    </bean>

    5)Properties配置注入

    <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl">
      <property name="properties">
        <props>
          <prop key="k1">v1</prop>
          <prop key="k2">v2</prop>
          <prop key="k3">v3</prop>
        </props>
      </property>
    </bean>

    配置文件模块化

    实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,也就是所谓的配置文件模块化

    1)并列的多个配置文件

    ApplicationContext act = new ClassPathXmlApplicationContext("beans1.xml","beans2.xml","...");

    2)主从配置文件

    <import resource="applicationContext-xxx.xml"/>

    注意:

    • 同一个xml中不能出现相同名称的bean,如果出现会报错
    • 多个xml如果出现相同名称的bean,不会报错,但是后加载的会覆盖前加载的bean

    知识小结

    Spring的重点配置

    <bean>标签:创建对象并放到spring的IOC容器
       id属性:在容器中Bean实例的唯一标识,不允许重复
       class属性:要实例化的Bean的全限定名
       scope属性:Bean的作用范围,常用是Singleton(默认)和prototype
     
    <constructor-arg>标签:属性注入
      name属性:属性名称
       value属性:注入的普通属性值
       ref属性:注入的对象引用值

    <property>标签:属性注入
       name属性:属性名称
       value属性:注入的普通属性值
       ref属性:注入的对象引用值
      <list>
         <set>
         <array>
            <map>
            <props>
    <import>标签:导入其他的Spring的分文件

    Spring注解开发

    Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率

    Spring常用注解

     说明:

    JDK11以后完全移除了javax扩展导致不能使用@resource注解。

    使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。

    <!--注解的组件扫描-->
    <context:component-scan base-package="com.lagou"></context:component-scan>

    Spring新注解

    * 非自定义的Bean的配置:<bean>

    * 加载properties文件的配置:<context:property-placeholder>

    * 组件扫描的配置:<context:component-scan>

    * 引入其他文件:<import>

     Spring整合Junit

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {SpringConfig.class})
    public class SpringJunitTest {
     
     @Autowired
      private AccountService accountService;
     
      //测试查询
      @Test
      public void testFindById() {
        Account account = accountService.findById(3);
        System.out.println(account);
     }
    }

    AOP

    常用的动态代理技术

    • JDK 代理 : 基于接口的动态代理技术·:利用拦截器(必须实现invocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,从而实现方法增强
    • CGLIB代理:基于父类的动态代理技术:动态生成一个要代理的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截技术拦截所有的父类方法的调用,顺势织入横切逻辑,对方法进行增强

     JDK动态代理方式

    @Component
        public class JdkProxyFactory {
            @Autowired
            private AccountService accountService;
    
            @Autowired
            private TransactionManager transactionManager;
    
            public AccountService createAccountServiceJdkProxy() {
                AccountService accountServiceProxy = null;
                accountServiceProxy = (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(),
                        accountService.getClass().getInterfaces(),
                        new InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args)
                                    throws Throwable {
                                Object result = null;
                                try {
                                    // 1.开启事务
                                    transactionManager.beginTransaction();
                                    // 2.业务操作
                                    result = method.invoke(accountService, args);
                                    // 3.提交事务 transactionManager.commit(); 
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    // 4.回滚事务 
                                    transactionManager.rollback();
                                }
                            }
                        }
            }
        }

    CGLIB动态代理方式

    @Component
        public class CglibProxyFactory {
            @Autowired
            private AccountService accountService;
    
            @Autowired
            private TransactionManager transactionManager;
    
            public AccountService createAccountServiceCglibProxy() {
                AccountService accountServiceProxy = null;
                /**
                 * 参数一:目标对象的字节码对象
                 * 参数二:动作类,实现增强功能
                 */
                accountServiceProxy = (AccountService)
                        Enhancer.create(accountService.getClass(), new MethodInterceptor() {
                            @Override
                            public Object intercept(Object o, Method method, Object[] objects,
                                                    MethodProxy methodProxy) throws Throwable {
                                Object result = null;
                                try {
                                    // 1.开启事务
                                    transactionManager.beginTransaction();
                                    // 2.业务操作
                                    result = method.invoke(accountService, objects);
                                    // 3.提交事务
                                    transactionManager.commit();
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    // 4.回滚事务
                                    transactionManager.rollback();
                                } finally {
                                    // 5.释放资源
                                    transactionManager.release();
                                }
                                return result;
                            }
                        });
                return accountServiceProxy;
            }
        }

     什么是AOP

    AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程。

     AOP 是 OOP(面向对象编程) 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

    这样做的好处是:

    1. 在程序运行期间,在不修改源码的情况下对方法进行功能增强
    2. 逻辑清晰,开发核心业务的时候,不必关注增强业务的代码
    3. 减少重复代码,提高开发效率,便于后期维护

    AOP底层实现

    实际上,AOP 的底层是通过 Spring 提供的的动态代理技术实现的。在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,再去调用目标对象的方法,从而完成功能的增强。

    * Target(目标对象):代理的目标对象
    * Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
    * Joinpoint(连接点):所谓连接点是指那些可以被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
    * Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
    * Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
      分类:前置通知、后置通知、异常通知、最终通知、环绕通知
    * Aspect(切面):是切入点和通知(引介)的结合
    * Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织
    入,而AspectJ采用编译期织入和类装载期织入

    AOP开发明确事项

    开发阶段(我们做的)

    1. 编写核心业务代码(目标类的目标方法) 切入点
    2. 把公用代码抽取出来,制作成通知(增强功能方法) 通知
    3. 在配置文件中,声明切入点与通知间的关系,即切面

    运行阶段(Spring框架完成的)

    Spring 框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。

    底层代理实现

    在 Spring 中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。
    当bean实现接口时,会用JDK代理模式
    当bean没有实现接口,用cglib实现( 可以强制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)

    基于XML的AOP开发

    XML配置AOP详解

    切点表达式

    execution([修饰符] 返回值类型 包名.类名.方法名(参数))

    • 访问修饰符可以省略
    • 返回值类型、包名、类名、方法名可以使用星号 * 代替,代表任意
    • 包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类
    • 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表

    切点表达式抽取

    当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替pointcut 属性来引用抽取后的切点表达式。

    <aop:config>
      <!--抽取的切点表达式-->
    <aop:pointcut id="myPointcut" expression="execution(* com.lagou.service..*.*
    (..))"> </aop:pointcut>
      <aop:aspect ref="myAdvice">
        <aop:before method="before" pointcut-ref="myPointcut"></aop:before>
      </aop:aspect>
    </aop:config>

    通知类型

    通知的配置语法:

    <aop:通知类型 method=“通知类中方法名” pointcut=“切点表达式"></aop:通知类型>

      注意:通常情况下,环绕通知都是独立使用的

    基于注解的AOP开发

    通知类型

    通知的配置语法:@通知注解(“切点表达式")

     当前四个通知组合在一起时,执行顺序如下:

    @Before -> @After -> @AfterReturning(如果有异常:@AfterThrowing)

    纯注解配置

    @Configuration
    @ComponentScan("com.lagou")
    @EnableAspectJAutoProxy //替代 <aop:aspectj-autoproxy />
    public class SpringConfig {
     
    }

    小结

    * 使用@Aspect注解,标注切面类
    * 使用@Before等注解,标注通知方法
    * 使用@Pointcut注解,抽取切点表达式
    * 配置aop自动代理 <aop:aspectj-autoproxy/> 或 @EnableAspectJAutoProxy

    利用aop注解和环绕通知案例

    public class TransactionManager {
      @Autowired
      ConnectionUtils connectionUtils;
      @Around("execution(* com.lagou.serivce..*.*(..))")
      public Object around(ProceedingJoinPoint pjp) {
        Object object = null;
        try {
          // 开启事务
          connectionUtils.getThreadConnection().setAutoCommit(false);
          // 业务逻辑
          pjp.proceed();
          // 提交事务
          connectionUtils.getThreadConnection().commit();
       } catch (Throwable throwable) {
          throwable.printStackTrace();
          // 回滚事务
          try {
            connectionUtils.getThreadConnection().rollback();
         } catch (SQLException e) {
            e.printStackTrace();
         }
       } finally {
          try {
            connectionUtils.getThreadConnection().setAutoCommit(true);
            connectionUtils.getThreadConnection().close();
            connectionUtils.removeThreadConnection();
         } catch (SQLException e) {
            e.printStackTrace();
         }
       }
        return object;
     }
    }

    Spring的JdbcTemplate

    JdbcTemplate是什么?

    JdbcTemplate是spring框架中提供的一个模板对象,是对原始繁琐的Jdbc API对象的简单封装。

    Spring的事务

    Spring中的事务控制方式

    Spring的事务控制可以分为编程式事务控制和声明式事务控制。

    编程式

    开发者直接把事务的代码和业务代码耦合到一起,在实际开发中不用。

    声明式

    开发者采用配置的方式来实现的事务控制,业务代码与事务代码实现解耦合,使用的AOP思想。

    编程式事务控制相关对象【了解】

    PlatformTransactionManager

    PlatformTransactionManager接口,是spring的事务管理器,里面提供了我们常用的操作事务的方法。

     注意:

    * PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类。
    * Dao层技术是jdbcTemplate或mybatis时:
      DataSourceTransactionManager
    * Dao层技术是hibernate时:
      HibernateTransactionManager
    * Dao层技术是JPA时:
      JpaTransactionManager

    TransactionDefinition

    TransactionDefinition接口提供事务的定义信息(事务隔离级别、事务传播行为等等)

    1)事务隔离级别

    设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读(幻读)。

    * ISOLATION_DEFAULT 使用数据库默认级别
    * ISOLATION_READ_UNCOMMITTED 读未提交
    * ISOLATION_READ_COMMITTED 读已提交
    * ISOLATION_REPEATABLE_READ 可重复读
    * ISOLATION_SERIALIZABLE 串行化

    2)事务传播行为

    事务传播行为指的就是当一个业务方法【被】另一个业务方法调用时,应该如何进行事务控制。

     * read-only(是否只读):建议查询时设置为只读

    * timeout(超时时间):默认值是-1,没有超时限制。如果有,以秒为单位进行设置

    TransactionStatus

    TransactionStatus 接口提供的是事务具体的运行状态。

     可以简单的理解三者的关系:事务管理器通过读取事务定义参数进行事务管理,然后会产生一系列的事务状态

    Spring中的事务控制主要就是通过这三个API实现的

    * PlatformTransactionManager 负责事务的管理,它是个接口,其子类负责具体工作
    * TransactionDefinition 定义了事务的一些相关参数
    * TransactionStatus 代表事务运行的一个实时状态

    基于XML的声明式事务控制【重点】

    在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。底层采用AOP思想来实现的。

    声明式事务控制明确事项:

    核心业务代码(目标对象) (切入点是谁?)
    事务增强代码(Spring已提供事务管理器))(通知是谁?)
    切面配置(切面如何配置?)

    事务参数的配置详解

    <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED"
    timeout="-1" read-only="false"/>
    * name:切点方法名称
    * isolation:事务的隔离级别
    * propogation:事务的传播行为
    * timeout:超时时间
    * read-only:是否只读

    CRUD常用配置

    <tx:attributes>
      <tx:method name="save*" propagation="REQUIRED"/>
      <tx:method name="delete*" propagation="REQUIRED"/>
      <tx:method name="update*" propagation="REQUIRED"/>
      <tx:method name="find*" read-only="true"/>
      <tx:method name="*"/>
    </tx:attributes>

    基于注解的声明式事务控制【重点】

    常用注解

    1)修改service层,增加事务注解

    @Service
    public class AccountServiceImpl implements AccountService {
          @Autowired
          private AccountDao accountDao;
        @Transactional(propagation = Propagation.REQUIRED, isolation =
        Isolation.REPEATABLE_READ, timeout = -1, readOnly = false)
          @Override
          public void transfer(String outUser, String inUser, Double money) {
            accountDao.out(outUser, money);
            int i = 1 / 0;
            accountDao.in(inUser, money);
         }
    }

    2)修改spring核心配置文件,开启事务注解支持

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w2.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">
      <!--省略之前datsSource、jdbcTemplate、组件扫描配置-->
     
      <!--事务管理器-->
      <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
      </bean>
     
      <!--事务的注解支持-->
      <tx:annotation-driven/>
    </beans>

    纯注解

    核心配置类

    @Configuration  // 声明为spring配置类
    @ComponentScan("com.lagou") // 扫描包
    @Import(DataSourceConfig.class) // 导入其他配置类
    @EnableTransactionManagement // 事务的注解驱动
    public class SpringConfig {
      @Bean
      public JdbcTemplate getJdbcTemplate(@Autowired DataSource dataSource) {
        return new JdbcTemplate(dataSource);
      }
      @Bean("transactionManager")
      public PlatformTransactionManager getPlatformTransactionManager(@Autowired
        DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
      }
    }

    数据源配置类

    @PropertySource("classpath:jdbc.properties")
    public class DataSourceConfig {
      @Value("${jdbc.driver}")
      private String driver;
      @Value("${jdbc.url}")
      private String url;
      @Value("${jdbc.username}")
      private String username;
      @Value("${jdbc.password}")
      private String password;
      @Bean
      public DataSource getDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
     }
    }

    Spring集成web环境

    ApplicationContext应用上下文获取方式

    应用上下文对象是通过  new ClasspathXmlApplicationContext(spring配置文件) 方式获取的,但是每次从容器中获得Bean时都要编写  new ClasspathXmlApplicationContext(spring配置文件) ,这样的弊端是配置文件加载多次,应用上下文对象创建多次。

    解决思路分析:

    在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了。

    Spring提供获取应用上下文的工具

    上面的分析不用手动实现,Spring提供了一个监听器ContextLoaderListener就是对上述功能的封
    装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供
    了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象。

    所以我们需要做的只有两件事:

    1. 在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)
    2. 使用WebApplicationContextUtils获得应用上下文对象ApplicationContext

    实现

    1)导入Spring集成web的坐标

    <dependency>
      <dependency>
       <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.5.RELEASE</version>
      </dependency>
       <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>

    2)配置ContextLoaderListener监听器

    <!--全局参数-->
    <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContext.xml</param-value></context-param>
    <!--Spring的监听器-->
    <listener>
      <listener-class>
       org.springframework.web.context.ContextLoaderListener
    </listener-class>
    </listener>

    3)通过工具获得应用上下文对象

    ApplicationContext applicationContext =  
      WebApplicationContextUtils.getWebApplicationContext(servletContext);
    Object obj = applicationContext.getBean("id");
  • 相关阅读:
    evernote100个做笔记的好方法
    平衡二叉树的调整模版
    晨间日记的奇迹
    hdu 2952 Counting Sheep
    hdu 1535 Invitation Cards
    poj 3259 Wormholes(spfa)
    poj 2263 Heavy Cargo(floyd)
    poj 3268 Silver Cow Party(SPFA)
    hdu 1690 Bus System
    hdu 3631 Shortest Path(Floyd)
  • 原文地址:https://www.cnblogs.com/zhf123/p/14432847.html
Copyright © 2011-2022 走看看