Spring配置数据源、注解开发、集成Junit、Web环境

一.Spring配置数据源

1.数据源(连接池)的作用

  • 数据源(连接池)是提高程序性能如出现的

  • 事先实例化数据源,初始化部分连接资源

  • 使用连接资源时从数据源中获取

  • 使用完毕后将连接资源归还给数据源

常见的数据源(连接池):DBCP、C3P0、BoneCP、Druid

2.数据源的使用步骤

​ ① 导入数据源的坐标和数据库驱动坐标

​ ② 创建数据源对象

​ ③ 设置数据源的基本连接信息

​ ④ 使用数据源获取连接资源和归还连接资源

我们可以手动创建数据源,也可以委托让Spring帮我们创建

下面先来演示一下手动创建数据源

3.手动创建Druid数据源

首先导入坐标

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.8</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>

然后按照步骤进行

public class TestDataSource {
    @Test
    public void testDruid(){
        //创建数据库连接池对象
        DruidDataSource ds = new DruidDataSource();
        //配置基本连接信息
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql:///jdbc");
        ds.setUsername("root");
        ds.setPassword("root");
        DruidPooledConnection connection = null;
        try {
            //从连接池中获取连接
            connection = ds.getConnection();
            System.out.println(connection);
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

com.mysql.jdbc.JDBC4Connection@693fe6c9

获取连接成功,打印地址

手动创建数据源,这里连接参数直接在代码中配置,程序耦合度较高,我们可以创建properties或ResouceBundle对象用于装载连接信息,进行解耦,提高程序的独立性,这里不再撰述,下面将演示用Spring来获取数据源并进行解耦

4.通过Spring创建Druid数据源

4.1.配置Bean以及用getBean获取数据源
<bean id="DataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///jdbc"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
  </bean>
public void testDruidBySpring(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        DruidDataSource ds = (DruidDataSource) applicationContext.getBean(DruidDataSource.class);
        try {
            DruidPooledConnection conn = ds.getConnection();
            System.out.println(conn);
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
}

com.mysql.jdbc.JDBC4Connection@906d29b

成功输出

另外,我们注意到,通过Spring容器创建Datasource对象,这里连接信息配置在Spring的xml文件中,也成功进行了解耦。但如果我们想更进一步的提高程序的独立性,我们可以将基本连接信息抽取到properties文件中。

4.2. 抽取jdbc连接信息配置文件

在xml使用properties需要引入另外一个命名空间,以免与默认命名空间混淆。

引入context命名空间和约束路径:

命名空间:xmlns:context=“http://www.springframework.org/schema/context”

约束路径:http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

然后使用el表达式关联配置

<?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.xsd
">
    <!--加载外部的properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!--使用el表达式加载properties里的配置-->
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.host}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
public void testDruidBySpring(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    DruidDataSource ds = applicationContext.getBean(DruidDataSource.class);
    try {
        DruidPooledConnection conn = ds.getConnection();
        System.out.println(conn);
        conn.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

输出结果表明可以正常获取连接

com.mysql.jdbc.JDBC4Connection@146587a2

二.Spring注解开发

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

1. 起步

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

<context:component-scan base-package="venture.study"></context:component-scan>

这里配置扫描venture.study包下的

2. 原始注解
注解说明其它
@Component使用在类上用于实例化Bean为了加强程序可读性,可以使用下面三种注解
@Controller使用在web层类上用于实例化Bean对Component的语义化
@Service使用在service层类上用于实例化Bean对Component的语义化
@Repository使用在dao层类上用于实例化Bean对Component的语义化
@AutoWired使用在字段上用于根据类型依赖注入1有相同类型的bean会报错2
@Qualifier结合@Autowired一起使用用于根据名称进行依赖注入1
@Resource3相当于@Autowired+@Qualifier,按照名称进行注入1
@Value注入普通属性一般结合properties使用进行解耦
@Scope标注Bean的作用范围
@PostConstruct使用在方法上标注该方法是Bean的初始化方法
@PreDestroy使用在方法上标注该方法是Bean的销毁方法
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常

  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常

  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

另外,该注释依赖于javax.annotation.Resource,jdk1.8及以下才有自带。若是9版本及以上,可以从pom中导入,否则无法注入,导致运行时要注入的对象找不到,直接报空指针异常

<dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
</dependency>

示例:

//Service层
@Service("userService")
public class UserServiceImpl implements UserService {
    @Value("好家伙")
    private String str;
    @Value("18")
    private int age;
    /*@Autowired
    @Qualifier("userDao")*/
    @Resource(name="userDao")
    private UserDao userDao;
    public void run() {
        System.out.println(str);
        System.out.println(age);
        userDao.run();
    } 
    
//@Component("userDao")
@Repository("userDao")
@Scope("singleton")
public class UserDaoImpl implements UserDao{
    public void run() {
        System.out.println("run方法执行了");
    }
}

//模拟视图层
public class AnnoController {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.run();
    }
}

好家伙
18
run方法执行了

3. 新注解

使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:

  • 非自定义的Bean的配置: <bean>
  • 加载properties文件的配置:<context:property-placeholder>
  • 组件扫描的配置:<context:component-scan>
  • 引入其他文件:<import>
注解说明其它
@Configuration用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan用于指定 Spring 在初始化容器时要扫描的包。 作用和在 Spring 的 xml 配置文件中的 一样相当于context:component-scan,在配置类上用
@Bean使用在方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource用于加载.properties 文件中的配置相当于context:property-placeholder
@Import用于导入其他配置类可以以数组形式导入多个配置类

//核心配置类
@Configuration
@ComponentScan("venture.study")
@Import({DataSourceConf.class})
public class SpringConf {
}

//bean配置类
@PropertySource("classpath:jdbc.properties")
public class DataSourceConf {
    @Value("${jdbc.driver}")
    private String driverClassName;
    @Value("${jdbc.host}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    @Bean(name="dataSource")
    public DataSource getDataSource() throws PropertyVetoException {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driverClassName);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        return ds;
    }
}

//测试类
    @Test
public void test() throws SQLException {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConf.class);
    DataSource dataSource = (DataSource)
        applicationContext.getBean("dataSource");
    Connection connection = dataSource.getConnection();
    System.out.println(connection);
}

注意到这里使用AnnotationConfigApplicationContext()加载核心配置类来创建Spring容器,这时我们可以直接删除applicationContext.xml配置文件,因为配置已经可以完全使用注解替代

输出结果

com.mysql.jdbc.JDBC4Connection@3ce3db41

注意:properties里的配置信息数据库用户名的key取username会与mysql关键字冲突,这里为了避免冲突加上了前缀jdbc.

三.Spring集成Junit

我们使用原始Junit测试Spring的时候,每次都必须先在家Spring容器然后通过getBean获取对象。这对于频繁的测试来说是非常不方便的。

在测试类中,每个测试方法都必须有以下两行代码

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");

为了减少代码冗余,我们可以

  • 让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它

  • 将需要进行测试Bean直接在测试类中进行注入

1.起步

​ 1)导入SpringJunit包4以及Junit包

​ 2)使用@Runwith注解替换原来的运行期

​ 3)使用@ContextConfiguration指定配置文件或配置类

​ 4)使用@Autowired注入需要测试的对象

​ 5) 创建测试方法进行测试

@RunWith(SpringJUnit4ClassRunner.class)//Spring测试单元替换原来的要运行期
@ContextConfiguration(classes = {SpringConf.class})//加载spring核心配置类
public class SpringJunitTest {
    @Autowired
    private UserService userService;

    @Test
    public void testUserService(){
            userService.run();
    }
}

输出结果:

好家伙
18
run方法执行了

注:本例是加载的配置类,如要加载spring核心配置文件 用@ContextConfiguration(value = {“classpath:applicationContext.xml”})

四.Spring集成Web环境

1.ApplicationContext应用上下文获取方式

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

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

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

Spring提供了一个监听器ContextLoaderListener就是对上述功能的封装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象。 所以我们需要做的只有两件事:

① 在web.xml中配置ContextLoaderListener监听器(记得在maven中导入spring-web坐标

<!--全局参数-->
<context-param>
  <param-name>contextConfigLocation</param-name><!--webApplicationContextUtils工具类通过该全局参数名获取配置文件-->
  <param-value>classpath:applicationContext.xml</param-value><!--Spring配置文件名直接在此更改即可-->
</context-param>
<!--加入Spring的监听器-->
<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>
<!--url映射servlet-->
<servlet>
    <servlet-name>WebApplicationContextUtilsTest</servlet-name>
    <servlet-class>venture.study.web.WebApplicationContextUtilsTest</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>WebApplicationContextUtilsTest</servlet-name>
    <url-pattern>/getwebcontext</url-pattern>
</servlet-mapping>

② 使用WebApplicationContextUtils获得应用上下文对象ApplicationContext

public class WebApplicationContextUtilsTest extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ApplicationContext applicationContext =
                WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());//需要ServletContext对象的传入
        UserService userService = (UserService)applicationContext.getBean("userService");
        userService.run();
    }
}

访问/getwebcontext,控制台输出结果:

UserDao的run方法执行了


  1. 进行属性注入无需set方法,其底层是通过暴力(对于私有属性)反射设置field. ↩︎ ↩︎ ↩︎

  2. @Autowired 根据数据类型从Spring容器中进行匹配,类似于getBean(Class requiredType)重载方法 ↩︎

  3. @Resource可以传name和type参数,装配顺序如下 ↩︎

  4. spring-test ↩︎

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值