统计
  • 建站日期:2021-03-10
  • 文章总数:518 篇
  • 评论总数:151 条
  • 分类总数:32 个
  • 最后更新:4月20日
文章 Spring

Spring全面需要注意的事项和知识点,复习必备

梦幻书涯
首页 Spring 正文

我们今天的主角在 spring-jdbc-5.0.2.RELEASE.jar 中,我们在导包的时候,除了要导入这个 jar 包 外,

还需要导入一个 spring-tx-5.0.2.RELEASE.jar(它是和事务相关的)


jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=8438031100






<aop:config>:配置aop的开始标签          aop:实现的办法是利用动态代理
    <aop:pointcut> 切入点:也就是将连接点增强的办法(切入点)
              切入点表达式的写法:
                    关键字:execution(表达式)
                    表达式:
                        访问修饰符  返回值  包名.包名.包名...类名.方法名(参数列表)
                    标准的表达式写法:
                        public void com.itheima.service.impl.AccountServiceImpl.saveAccount()
                    访问修饰符可以省略
                        void com.itheima.service.impl.AccountServiceImpl.saveAccount()
                    返回值可以使用通配符,表示任意返回值
                        * com.itheima.service.impl.AccountServiceImpl.saveAccount()
                    包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.
                        * *.*.*.*.AccountServiceImpl.saveAccount())
                    包名可以使用..表示当前包及其子包
                        * *..AccountServiceImpl.saveAccount()
                    类名和方法名都可以使用*来实现通配
                        * *..*.*()
                    参数列表:
                        可以直接写数据类型:
                            基本类型直接写名称           int
                            引用类型写包名.类名的方式   java.lang.String
                        可以使用通配符表示任意类型,但是必须有参数
                        可以使用..表示有无参数均可,有参数可以是任意类型
                    全通配写法:
                        * *..*.*(..)

                    实际开发中切入点表达式的通常写法:
                        切到业务层实现类下的所有方法
                            * com.itheima.service.impl.*.*(..)

     <aop:aspect>切面    也就是切入点(连接点增强的办法)和同事(事务)的结合
           id  切面的唯一标识
            ref="txManager"   事务的bean唯一标识

            两种加起来就是切面(切入点和通知的结合)


        <aop:before 配置前置通知:开启事务>

        <aop:after-returning 配置后置通知:提交事务->

        <aop:after-throwing 配置异常通知:回滚事务>

        <aop:after 配置最终通知:释放连接>

        <aop:around 配置环绕通知 详细的注释请看Logger类中>配置环绕通知:
        也就是整个invoke()办法,可以在里面配置前置,后置,异常,最后通知和切入点办法
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}

    </aop:aspect>






    <aop:config>
        <aop:pointcut id="pt1" expression="execution(* com.sise.servlet.impl.*.*(..))"/>
        <aop:aspect id="txAdvice" ref="txManager">

          
            <!--配置前置通知:开启事务-->
            <aop:before method="beginTransaction" pointcut-ref="pt1"/>
            <!--配置后置通知:提交事务-->
            <aop:after-returning method="commitTransaction" pointcut-ref="pt1"/>
            <!--配置异常通知:回滚事务-->
            <aop:after-throwing method="rollbackTransaction" pointcut-ref="pt1"/>
            <!--配置最终通知:释放连接-->
            <aop:after method="closeTransaction" pointcut-ref="pt1"/>

            <aop:around method="aroundTransaction" pointcut-ref="pt1"/>
        </aop:aspect>
    </aop:config>


记住用spring提供的内置事务管理器,就不需要线程和当前链接绑定(也就是说ConnectionUtils这个类可以删除)
        而且Impl.daoimpl类中的sqlq语句不能加Connectionutils.getThreadConnection(),否则事务失败,spring本身已经弄好了


<!-- spring中基于XML的声明式事务控制配置步骤
        1、配置事务管理器
        2、配置事务的通知
                此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的
                使用tx:advice标签配置事务通知
                    属性:
                        id:给事务通知起一个唯一标识
                        transaction-manager:给事务通知提供一个事务管理器引用
        3、配置AOP中的通用切入点表达式
        4、建立事务通知和切入点表达式的对应关系
        5、配置事务的属性
               是在事务的通知tx:advice标签的内部

     -->
    <!-- 配置事务管理器
     需要提供数据源,用来绑定线程和连接
     -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"></property>
    </bean>

    <!-- 配置事务的通知
    transaction-manager》》》》事务管理器的唯一id标识
    -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 配置事务的属性
                isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。一部可以不写
                propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
                一般》》》propagation="REQUIRED" read-only="false"
                和》》》》propagation="SUPPORTS" read-only="true"
                两者同时出现

                read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
                timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
                rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
                no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。
        -->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="false"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!-- 配置aop-->
    <aop:config>
        <!-- 配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* com.sise.servlet.impl.*.*(..))"></aop:pointcut>
        <!--建立切入点表达式和事务通知的对应关系
         建立一个切面》》
         需要事务和切入点
         advice-ref="txAdvice"(事务)
         pointcut-ref="pt1"(切入点)

         -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>



测试类


@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = "bean.xml")这样就会出现出错,找不到该类,必须加classpath:说明该文件是再根路径下
@ContextConfiguration(locations = "classpath:bean.xml")

/*
* 下面这句话等价于--->        ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
        IUserServlet ac = (IUserServlet) acs.getBean("userServlet");
        * 就是类似加载了bean.xml,又因为完成注解已经用SpringConfiguration类替代了bean.xml,故加载这个就等价加载bean.xml
        *
        *
        *
        * @ContextConfiguration 注解:
        * locations 属性:用于指定配置文件的位置。如果是类路径下,需要用 classpath:表明
        * classes 属性:用于指定注解的类。当不使用 xml 配置时,需要用此属性指定注解类的位置
* */
//@ContextConfiguration(classes = SpringConfiguration.class)


public class test {}




@Autowired @Qualifier("userServlet") private IUserServlet userServlet;
 //目前IUserServlet有三个对象名,Autowired这样就不行,无法自动授予那个对象,
因此需要Qualifier对那个名字进行授权 //这个是注解和xml配置的实现办法


/*
        * @ContextConfiguration(locations = "classpath:bean.xml")作用是:获取容器,有了这句话就不需要下面这2句话
        *
        *
       ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
       IUserServlet ac = (IUserServlet) acs.getBean("userServlet");也是为了获取容器
       *
       *
       这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。
        @ContextConfiguration(classes = SpringConfiguration.class)
        @RunWith(SpringJUnit4ClassRunner.class)
        这两句话不写,直接用junit不行,会提示  @Autowired对象空指针异常,原因在下面

        * 针对上述问题,我们需要的是程序能自动帮我们创建容器。
        * 一旦程序能自动为我们创建 spring 容器,我们就 无须手动创建了,
        * 问题也就解决了。 我们都知道,junit 单元测试的原理(在 web 阶段课程中讲过),
        * 但显然,junit 是无法实现的,因为它自 己都无法知晓我们是否使用了 spring 框架,
        * 更不用说帮我们创建 spring 容器了。不过好在,junit 给我们暴露 了一个注解,
        * 可以让我们替换掉它的运行器。 这时,我们需要依靠 spring 框架,
        * 因为它提供了一个运行器,可以读取配置文件(或注解)来创建容器。我 们只需要告诉它配置文件在哪就行了。
        *
        *        @ContextConfiguration(classes = SpringConfiguration.class)
        @RunWith(SpringJUnit4ClassRunner.class)这两句话就是这个作用,用来替换
        *  ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
       IUserServlet ac = (IUserServlet) acs.getBean("userServlet");来获取容器
        * */
//        ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
//        IUserServlet ac = (IUserServlet) acs.getBean("userServlet");




动态代理



@Component("beanFactory")
public class BeanFactory {

    @Autowired
    private TransactionManager txManager;

    public void setTxManager(TransactionManager txManager) {
        this.txManager = txManager;
    }

    public void setUserServlet(IUserServlet userServlet) {
        this.userServlet = userServlet;
    }

    @Autowired
    private IUserServlet userServlet;

    //proxyUserServlet代理对象的bean
    //userServlet被代理对象的bean

    /*
    * 基于接口的动态代理-->也就是被代理的对象userServlet必须实现接口
 动态代理:
         *  特点:字节码随用随创建,随用随加载
         *  作用:不修改源码的基础上对方法增强
         *  分类:
         *      基于接口的动态代理
         *      基于子类的动态代理
         *  基于接口的动态代理:
         *      涉及的类:Proxy
         *      提供者:JDK官方
         *  如何创建代理对象:
         *      使用Proxy类中的newProxyInstance方法
         *  创建代理对象的要求:
         *      被代理类最少实现一个接口,如果没有则不能使用
         * 也就是被代理的对象userServlet必须是实现接口的类对象
         *
    * 参数1:ClassLoader loader---> 它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
             通俗点就是想代理那个对象,就写这个对象的字节码类加载器
      参数2:Class<?>[] interfaces--->它是用于让代理对象和被代理对象有相同方法。固定写法。
      *       通俗点就是让代理对象和被代理对象都有相同的办法,这样被代理对象(userServlet)可以直接调用
      * 代理对象(proxyUserServlet)也可以直接调用
      参数3:InvocationHandler对象--->  它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
         *          此接口的实现类都是谁用谁写
    *
    * 参数含义:
* ClassLoader:和被代理对象使用相同的类加载器。
* Interfaces:和被代理对象具有相同的行为。实现相同的接口。
* InvocationHandler:如何代理。
* 策略模式:使用场景是:
* 数据有了,目的明确。
* 如何达成目标,就是策略。
    *
    *
    * 参数1:Object proxy--->代理对象
    * 参数2:Method method--->当前执行的办法
    * 参数3:Object[] args--->当前执行办法所需的参数,数组从0开始
    *
    * */

    InvocationHandler handler = new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("执行代理对象的办法");
            Object rtValue = null;
            //提供增强的代码
            if ("test".equals(method.getName())) {
                return method.invoke(userServlet, args);
            }
            try {
                txManager.beginTransaction();
                if ("transfer".equals(method.getName())) {
                    System.out.println("动态代理-->transfer");
                    args[2] = 1000;
                }
                rtValue = method.invoke(userServlet, args);
                txManager.commitTransaction();
                return rtValue;
            } catch (Exception e) {
                txManager.rollbackTransaction();
                throw new RuntimeException(e);
            } finally {
                txManager.commitTransaction();
            }
        }
    };

    @Bean("proxyUserServlet")
    public IUserServlet getIUserServlet() {
        return (IUserServlet) Proxy.newProxyInstance(
                userServlet.getClass().getClassLoader(),
                userServlet.getClass().getInterfaces(),
                handler
        );
    }
}










// @Bean("EnhancerBeanFactory")
    public IUserServlet getUserServlet() {

        return (IUserServlet) Enhancer.create(userServlet.getClass(), userServlet.getClass().getInterfaces(), new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                /**
                 * 执行IUserServlet类任何方法都会经过该方法
                 * @param proxy:代理对象
                 * @param method:当前执行的办法
                 * @param args:当前执行办法所需的参数
                 *    以上三个参数和基于接口的动态代理中invoke方法的参数是一样的
                 * @param methodProxy :当前执行方法的代理对象
                 * @return
                 * @throws Throwable
                 */
                System.out.println("执行代理对象的 Enhancer.create办法");
                Object rtValue = null;
                //提供增强的代码
                if ("test".equals(method.getName())) {
                    return method.invoke(userServlet, args);
                }
                try {
                    txManager.beginTransaction();
                    if ("transfer".equals(method.getName())) {
                        System.out.println("动态代理-->transfer");

                    //    args[2] = 1000;//java.lang.IllegalArgumentException: argument type mismatch
                        //这个错误就是说参数类型不一致,因为userServlet.transfer("王成","王妃", (float) 500)
                        //最后一个参数是float
                        //args[2] = 1000;这个是int型,因此需要args[2] = 1000f;让他也是float
                        args[2] = 1000f;
                    }
                    rtValue = method.invoke(userServlet, args);
                    txManager.commitTransaction();
                    return rtValue;
                } catch (Exception e) {
                    txManager.rollbackTransaction();
                    throw new RuntimeException(e);
                } finally {
                    txManager.commitTransaction();
                }

            }
        });
    }

}






JdbcConfig.java



public class JdbcConfig {

    @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("dataSource")
    public DataSource createDataSource() {
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        try {
            cpds.setDriverClass(driver);
            cpds.setJdbcUrl(url);
            cpds.setUser(username);
            cpds.setPassword(password);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return cpds;
    }

    @Bean("template")
    public JdbcTemplate returnTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean("runner")
    public QueryRunner returnrunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }
}







线程和链接绑定



//数据库连接工具类:目 目的就是将当前线程和当前连接绑定,使得事务正常进行
//而不是每次都进行连接的创建,也就是银行转账问题,没有事务因此每次执行对数据库的操作都创建连接
//因此会让数据不一致

@Component("connectionUtils")
public class ConnectionUtils {
    private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();


    @Autowired
    private DataSource dataSource;

    public Connection getConnection() {
        try {
            //1.先从ThreadLocal上获取
            Connection conn = tl.get();
            //2.判断当前线程上是否有连接
            if (conn == null) {
                //3.从数据源中获取一个连接,并且存入ThreadLocal中
                conn = dataSource.getConnection();
                tl.set(conn);
            }
            //4.返回当前线程上的连接
            return conn;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void CloseConnection() {
        tl.remove();
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
}





@Configuration
@ComponentScan(basePackages = "com.sise")
@Import({JdbcConfig.class})
@PropertySource("classpath:jdbc.properties")
@EnableAspectJAutoProxy
//如果要用注解来配置AOP的支持和切面,只能用环绕通知,用前置,后置,最终,异常配置不了,这个只能支持xml配置
public class SpringConfiguration {
}






/**
 * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
 */
@Component("txManager")
public class TransactionManager {

    @Autowired
    private ConnectionUtils connectionUtils;

    public void setConnectionUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    /**
     * 开启事务
     */
    public void beginTransaction() {
        try {
            System.out.println("配置前置通知:TransactionManager在切入点方法执行之前执行");
            connectionUtils.getConnection().setAutoCommit(false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 提交事务
     */
    public void commitTransaction() {
        try {
            System.out.println("配置后置通知:TransactionManager在切入点方法正常执行之后值。它和异常通知永远只能执行一个");
            connectionUtils.getConnection().commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 回滚事务
     */
    public void rollbackTransaction() {
        try {
            System.out.println("配置异常通知:TransactionManager在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个");
            connectionUtils.getConnection().rollback();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 关闭事务
     */
    public void closeTransaction() {
        try {
            System.out.println("配置最终通知:TransactionManager无论切入点方法是否正常执行它都会在其后面执行");
            connectionUtils.getConnection().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 环绕通知事务
     */

    public Object aroundTransaction(ProceedingJoinPoint pjp) {
        System.out.println("配置环绕通知:TransactionManager切入点和通知");
        Object rtValue = null;
        try {
            Object[] args = pjp.getArgs();//得到方法执行所需的参数
            beginTransaction();
            rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
            commitTransaction();
            return rtValue;
        } catch (Throwable t) {
            rollbackTransaction();
            throw new RuntimeException(t);
        } finally {
            closeTransaction();
        }
    }
}






/*
这些就是xml配置内容,这个类就是替代bean.xml,从而不需要bean.xml文件

@Configuration-->告诉spring这个就是等价Bean.xml文件
@ComponentScan
等价下面的
 <context:component-scan base-package="com.sise"/>
 用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。


下面将创建一个类JdbcConfig ,实现下面代码的替换
从而用@bean存再spring容器中,就等价  <bean id=""  class="">
*
*   <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="DBCPdataSource"></property>
    </bean>
    *
    *
    *     <!--  配置DBCP数据源 -->
    <bean id="DBCPdataSource"
          class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///ssm"></property>
        <property name="username" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>
*
* */



/**
 * 该类是一个配置类,它的作用和bean.xml是一样的
 * spring中的新注解
 * Configuration
 *     作用:指定当前类是一个配置类
 *     细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
 * ComponentScan
 *      作用:用于通过注解指定spring在创建容器时要扫描的包
 *      属性:
 *          value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
 *                 我们使用此注解就等同于在xml中配置了:
 *                      <context:component-scan base-package="com.itheima"></context:component-scan>
 *  Bean
 *      作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
 *      属性:
 *          name:用于指定bean的id。当不写时,默认值是当前方法的名称
 *      细节:
 *          当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
 *          查找的方式和Autowired注解的作用是一样的
 *  Import
 *      作用:用于导入其他的配置类
 *      属性:
 *          value:用于指定其他配置类的字节码。
 *                  当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
 *  PropertySource
 *      作用:用于指定properties文件的位置
 *      属性:
 *          value:指定文件的名称和路径。
 *                  关键字:classpath,表示类路径下
 */
@Configuration
@ComponentScan(basePackages = "com.sise")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbc.properties")
/*
 用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。*/
public class SpringConfiguration {
}



/*
这些就是xml配置内容,这个类就是替代bean.xml,从而不需要bean.xml文件

@Configuration-->告诉spring这个就是等价Bean.xml文件
@ComponentScan
等价下面的
 <context:component-scan base-package="com.sise"/>
 用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。


下面将创建一个类JdbcConfig ,实现下面代码的替换
从而用@bean存再spring容器中,就等价  <bean id=""  class="">
*
*   <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="DBCPdataSource"></property>
    </bean>
    *
    *
    *     <!--  配置DBCP数据源 -->
    <bean id="DBCPdataSource"
          class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///ssm"></property>
        <property name="username" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>
*
* */



/**
 * 该类是一个配置类,它的作用和bean.xml是一样的
 * spring中的新注解
 * Configuration
 *     作用:指定当前类是一个配置类
 *     细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
 * ComponentScan
 *      作用:用于通过注解指定spring在创建容器时要扫描的包
 *      属性:
 *          value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
 *                 我们使用此注解就等同于在xml中配置了:
 *                      <context:component-scan base-package="com.itheima"></context:component-scan>
 *  Bean
 *      作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
 *      属性:
 *          name:用于指定bean的id。当不写时,默认值是当前方法的名称
 *      细节:
 *          当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
 *          查找的方式和Autowired注解的作用是一样的
 *  Import
 *      作用:用于导入其他的配置类
 *      属性:
 *          value:用于指定其他配置类的字节码。
 *                  当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
 *  PropertySource
 *      作用:用于指定properties文件的位置
 *      属性:
 *          value:指定文件的名称和路径。
 *                  关键字:classpath,表示类路径下
 */
@Configuration
@ComponentScan(basePackages = "com.sise")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbc.properties")
/*
 用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。*/
public class SpringConfiguration {
}






 <context:component-scan base-package="com.sise"/>
    <!--配置QueryRunner-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">


        <!--        如果用QueryRunner封装数据库模板据库需要用构造函数引入数据源
                     如果用JdbcTemplate

                     <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
                <property name="dataSource" ref="DBCPdataSource"></property>
            </bean>
            就不需要用构造函数

        -->
        <!--注入数据源-->
        <constructor-arg name="ds" ref="DBCPdataSource"></constructor-arg>
        <!-- 如果想线程和连接绑定,则需要再daoImpl里面的sql语句前面添加connectionUtils.getThreadConnection(),

        return runner.query(connectionUtils.getThreadConnection(),"select * from mybatisacount"
        , new BeanListHandler<AcountBean>(AcountBean.class));

        而且要注掉这个1语句:<constructor-arg name="ds" ref="dataSource"></constructor-arg>
        这个语句不注掉,就会创建多个连接,使事务不能使用


        -->
        <!--        <property name="runner" ref="runner"></property>  用这个就会出现错误-->
    </bean>


    <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="DBCPdataSource"></property>
    </bean>


    <!-- 配置c3p0数据源 -->
    <bean id="c3p0dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm"></property>
        <property name="user" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>


    <!--  配置Spring内置数据源 -->
    <bean id="SpringDataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/ssm"></property>
        <property name="username" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>


    <!--  配置DBCP数据源 -->
    <bean id="DBCPdataSource"
          class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///ssm"></property>
        <property name="username" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>





<!--        如果用QueryRunner封装数据库模板据库需要用构造函数引入数据源
             如果用JdbcTemplate

             <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="DBCPdataSource"></property>
    </bean>
    就不需要用构造函数

-->
        <!--注入数据源-->
        <constructor-arg name="ds" ref="DBCPdataSource"></constructor-arg>
        <!-- 如果想线程和连接绑定,则需要再daoImpl里面的sql语句前面添加connectionUtils.getThreadConnection(),

        return runner.query(connectionUtils.getThreadConnection(),"select * from mybatisacount"
        , new BeanListHandler<AcountBean>(AcountBean.class));

        而且要注掉这个1语句:<constructor-arg name="ds" ref="dataSource"></constructor-arg>
        这个语句不注掉,就会创建多个连接,使事务不能使用


        -->
        <!--        <property name="runner" ref="runner"></property>  用这个就会出现错误-->
    </bean>


    <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="DBCPdataSource"></property>
    </bean>


    <!-- 配置c3p0数据源 -->
    <bean id="c3p0dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm"></property>
        <property name="user" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>


    <!--  配置Spring内置数据源 -->
    <bean id="SpringDataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/ssm"></property>
        <property name="username" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>


    <!--  配置DBCP数据源 -->
    <bean id="DBCPdataSource"
          class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///ssm"></property>
        <property name="username" value="root"></property>
        <property name="password" value="8438031100"></property>
    </bean>


版权说明
文章采用: 《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权。
版权声明:未标注转载均为本站原创,转载时请以链接形式注明文章出处。如有侵权、不妥之处,请联系站长删除。敬请谅解!

这篇文章最后更新于2020-8-6,已超过 1 年没有更新,如果文章内容或图片资源失效,请留言反馈,我们会及时处理,谢谢!
Mybatis全面需要注意的事项和知识点,复习必备
« 上一篇
MySQL存储过程与函数--范例,让你更容易
下一篇 »

发表评论

HI ! 请登录
注册会员,享受下载全站资源特权。
Array

日历

热门文章