2021-09-19 Spring5 IoC与DI注解开发

Spring5 IoC与DI注解开发

1 Spring配置数据源

1.1 数据源(连接池)的作用

  • 数据源(连接池)是提高程序性能如出现的
  • 事先实例化数据源,初始化部分连接资源
  • 使用连接资源时从数据源中获取
  • 使用完毕后将连接资源归还给数据源
    常见的数据源(连接池): DBCP、 C3P0、 BoneCP、 Druid等

1.2 数据源的开发步骤

数据源的手动创建

数据库 数据源依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>
<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.6</version>
</dependency>

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.4.0</version>
    <scope>test</scope>
</dependency>

测试类

package com.raphuscucullatus.test;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.testng.annotations.Test;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.util.ResourceBundle;

/**
 * c3p0 德鲁伊 数据源测试类
 *
 * @author raphus cucullatus
 * @version 2021/9/18 1:03
 * @since JDK8
 */
public class DataSourceTest {
    /**
     * 手动配置连接参数创建c3p0数据源
     */
    @Test
    public void testManualCreateDataSource() throws Exception {
        //创建数据源
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //设置数据库连接参数
        dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://127.168.2.8:3306/jdbc");
        dataSource.setUser("root");
        dataSource.setPassword("088.5741");
        //获得连接对象
        Connection connection = dataSource.getConnection();
        System.out.println(connection);

    }

    /**
     * 手动配置连接参数创建Druid数据源
     */
    @Test
    public void testManualCreateDruidDataSource() throws SQLException {
        //创建数据源
        DruidDataSource dataSource = new DruidDataSource();
        //设置数据库连接参数
        dataSource.setPassword("root");
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/jdbc");
        dataSource.setUsername("root");
        dataSource.setPassword("088.5741");
        //获得连接对象
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }


    /**
     * 通过读取配置文件创建c3p0数据源
     */
    @Test
    public void testCreateDataSource() throws PropertyVetoException, SQLException {

        //加载类路径下的jdbc.properties
        ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc");
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //使用resourceBundle读取配置文件信息
        dataSource.setDriverClass(resourceBundle.getString("jdbc.driver"));
        dataSource.setJdbcUrl(resourceBundle.getString("jdbc.url"));
        dataSource.setUser(resourceBundle.getString("jdbc.username"));
        dataSource.setPassword(resourceBundle.getString("jdbc.password"));
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();

    }

    /**
     * 通过读取配置文件创建Druid数据源
     */
    @Test
    public void testCreateDruidDataSource() {
        DataSource dataSource;
        Properties properties = new Properties();
        try {
            properties.load(DataSourceTest.class.getClassLoader().getResourceAsStream("druiddatasource.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

c3p0数据源配置文件

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jdbc
jdbc.username=root
jdbc.password=088.5741

druid数据源配置文件

url=jdbc:mysql://127.0.0.1:3306/jdbc
username=root
password=088.5741
maxActive=20
initialSize=5
maxWait=6000
asyncInit=true

从硬编码到配置文件,对数据源的开发进行解耦

1.3 Spring配置数据源

除了响应的数据库 数据源依赖之外,还要导入spring依赖

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

配置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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jdbc"></property>
        <property name="user" value="root"></property>
        <property name="password" value="088.5741"></property>
    </bean>
</beans>

测试

   /**
     * 通过spring容器产生c3p0数据源
     */
    @Test
    public void testSpringCreateDruidDataSource() throws SQLException {
        ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
//        DataSource dataSource = (DataSource)application.getBean("dataSource");
        DataSource dataSource = application.getBean(DataSource.class);
        Connection connection = dataSource.getConnection();
        System.out.println("通过spring容器获取的connection:"+connection);
        connection.close();
    }

1.4 Spring抽取配置文件

数据源配置文件信息

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jdbc
jdbc.username=root
jdbc.password=088.5741

spring核心配置文件
注意:需要在beans标签内添加属性contenxt命名空间(如下加粗部分为添加)

<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

>

以及beans内添加如下子标签引入外部properties文件(其中location属性为外部properties的路径):

<context:property-placeholder location=“classpath:jdbc.properties”/>

<?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"/>
<!--  使用spring表达式获取properties文件中的值  -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

</beans>

测试代码

    /**
     * 通过spring容器产生c3p0数据源
     */
    @Test
    public void testSpringCreateDataSource() throws SQLException {
        ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource dataSource = (DataSource)application.getBean("dataSource");
//        DataSource dataSource = application.getBean(DataSource.class);
        Connection connection = dataSource.getConnection();
        System.out.println("通过spring容器获取的connection:"+connection);
        connection.close();
    }
    /**
     * 通过spring容器产生Druid数据源
     */
    @Test
    public void testSpringCreateDruidDataSource() throws SQLException {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        DruidDataSource druidDataSource = (DruidDataSource)applicationContext.getBean("druidDataSource");
        DruidPooledConnection connection = druidDataSource.getConnection();
        System.out.println("通过Spring容器获取的connection"+connection);
        connection.close();
    }

2 Spring注解开发

2.1 注解快速入门

通过以下原始注解减少我的配置量,提高开发效率
在这里插入图片描述

案例:使用ComponentAutowired Qualifier替代xml配置

spring核心配置文件:

<!--    配置组件扫描    -->
<context:component-scan base-package="com.raphuscucullatus"/>

Dao层

package com.raphuscucullatus.dao.impl;

import com.raphuscucullatus.dao.UserDao;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author raphus cucullatus
 * @version 2021/9/17 18:25
 * @since JDK8
 */
@Component("userDao")//等效于<bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl"/>
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("save running....");
    }
}

Service层

package com.raphuscucullatus.service.impl;

import com.raphuscucullatus.dao.UserDao;
import com.raphuscucullatus.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

/**
 * UserService实现类
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:42
 * @since JDK8
 */
@Component("userService")//等效于<bean id="userService" class="com.raphuscucullatus.service.impl.UserServiceImpl"/>
public class UserServiceImpl implements UserService {

    /**
     * set注入
     * @param userDao
     */
    @Autowired
    @Qualifier("userDao")//等效于set注入<property name="userDao" ref="userDao"/>
    private UserDao userDao;
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }
    @Override
    public void save() {
        userDao.save();
    }
}

测试

package com.raphuscucullatus.controller;

import com.raphuscucullatus.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * 模拟控制层的测试用例
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:51
 * @since JDK8
 */
public class UserControllerTest {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = app.getBean(UserService.class);
        userService.save();

    }
}

2.2 原始注解详解

核心配置文件

**注意:**需要使用到context命名空间(在beans标签的属性中添加)

<?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="jdbc.properties"/>

    <!--    配置组件扫描(不配置包扫描,spring将无法招到需要注入的类)    -->
    <context:component-scan base-package="com.raphuscucullatus"/>

</beans>

在dao层使用注解配合

package com.raphuscucullatus.dao.impl;

import com.raphuscucullatus.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
 * @author raphus cucullatus
 * @version 2021/9/17 18:25
 * @since JDK8
 */
//@Component("userDao")//等效于<bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl"/>
@Repository("userDao")//等效于@Component("userDao") 并表明该类为dao层的类
public class UserDaoImpl implements UserDao {
    
    /**
     * 用户名
     */
    //同 <property name="user" value="${jdbc.username}"></property>
    @Value("${jdbc.username}")//通过注解配置读取外部properties文件的值
    private String userName;
    /**
     * 密码
     */
    //同 <property name="password" value="${jdbc.password}"></property>
    @Value("${jdbc.password}")//通过注解配置读取外部properties文件的值
    private String password;
	
    @PostConstruct//执行构造器后执行发方法(了解)
    public void init (){
        System.out.println("UserDaoImpl初始化");
    }
    
    @PreDestroy//销毁容器前执行(了解)
    public void destroy (){
        System.out.println("UserDaoImpl被销毁");
    }

    @Override
    public void save() {
        System.out.println("用户名:"+userName+",密码:"+password);
        System.out.println("save running....");

    }
}

在service层使用注解配合

package com.raphuscucullatus.service.impl;

import com.raphuscucullatus.dao.UserDao;
import com.raphuscucullatus.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;


/**
 * UserService实现类
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:42
 * @since JDK8
 */
//@Component("userService")//等效于<bean id="userService" class="com.raphuscucullatus.service.impl.UserServiceImpl"/>
@Service("userService")//等效于@Component("userService") 表示在service层
@Scope("singleton")
public class UserServiceImpl implements UserService {
    /**
     * set注入
     * @param userDao
     */
//    @Autowired//不使用@Qualifier("userDao")注解时,默认匹配数据类型(.class)进行注入,如果容器中有多个型同类型时必须使用@Qualifier("userDao")注解
//    @Qualifier("userDao")//等效于set注入<property name="userDao" ref="userDao"/>, @Qualifier必须结合@Autowired使用
    @Resource(name="userDao")//等效于@Qualifier+@Autowired
    private UserDao userDao;
    //使用注解配置时可以不定义该set方法
//    public void setUserDao(UserDao userDao){
//        this.userDao=userDao;
//    }

    @Override
    public void save() {
        userDao.save();
    }
}

模拟控制层的测试用例

package com.raphuscucullatus.controller;

import com.raphuscucullatus.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import java.awt.peer.ScrollPanePeer;

/**
 * 模拟控制层的测试用例
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:51
 * @since JDK8
 */
public class UserControllerTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = app.getBean(UserService.class);
        userService.save();
        app.close();

    }
}

2.3 新注解详解

解决原始注解的问题

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

  • 非自定义的Bean的配置:
  • 加载properties文件的配置: context:property-placeholder
  • 组件扫描的配置: context:component-scan
  • 引入其他核心配置文件文件:
<?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"
>
	<!--    非自定义的Bean的配置    -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
       <property name="driverClass" value="${jdbc.driver}"></property>
       <property name="jdbcUrl" value="${jdbc.url}"></property>
       <property name="user" value="${jdbc.username}"></property>
       <property name="password" value="${jdbc.password}"></property>
    </bean>
	<!--  加载外部的properties文件  -->
    <context:property-placeholder location="jdbc.properties"/>

    <!--    配置组件扫描(不配置包扫描,spring将无法招到需要注入的类)    -->
    <context:component-scan base-package="com.raphuscucullatus"/>
    
    <!--    引入外部配置文件    -->
	<import resource="applicationContext-user.xml"/>

</beans>

在这里插入图片描述
核心配置类

不引入外部配置

package com.raphuscucullatus.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;

import javax.sql.DataSource;

/**
 * spring核心配置类
 *
 * @author raphus cucullatus
 * @version 2021/9/18 23:10
 * @since JDK8
 */
@Configuration//告诉Spring配置信息到该类查找(即:用此类来代替配置文件)
@ComponentScan("com.raphuscucullatus")//同:<context:component-scan base-package="com.raphuscucullatus"/>
@PropertySource("jdbc.properties")//同:<context:property-placeholder location="jdbc.properties"/>
//@Import({DataSourceConfiguration.class})//同:<import resource="applicationContext-user.xml"/>
public class SpringConfiguration {

    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String user;
    @Value("${jdbc.password}")
    private String password;
    @Bean("dataSource")

//    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
//       <property name="driverClass" value="${jdbc.driver}"></property>
//       <property name="jdbcUrl" value="${jdbc.url}"></property>
//       <property name="user" value="${jdbc.username}"></property>
//       <property name="password" value="${jdbc.password}"></property>
//    </bean>
//    对于非自定义类无法在其源码上添加@Component("dataSource")注解,解决方案如下:@Bean()
    public DataSource getDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }

}

引入外部配置

package com.raphuscucullatus.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;

/**
 * spring核心配置类
 *
 * @author raphus cucullatus
 * @version 2021/9/18 23:10
 * @since JDK8
 */
@Configuration//告诉Spring配置信息到该类查找(即:用此类来代替配置文件)
@ComponentScan("com.raphuscucullatus")//同:<context:component-scan base-package="com.raphuscucullatus"/>
@PropertySource("jdbc.properties")//同:<context:property-placeholder location="jdbc.properties"/>
@Import({DataSourceConfiguration.class})//<import resource="applicationContext-user.xml"/>
public class SpringConfiguration {
}
package com.raphuscucullatus.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;

/**
 * 数据源配置类
 * @author raphus cucullatus
 * @version 2021/9/18 23:46
 * @since JDK8
 */
public class DataSourceConfiguration {
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String user;
    @Value("${jdbc.password}")
    private String password;
    @Bean("dataSource")
    public DataSource getDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }
}

两种方式都可此测试类测试

/**
 * 通过注解配置 spring容器产生Druid数据源
 */
@Test
public void testAnnotationCreateDruidDataSource() throws SQLException {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    DruidDataSource druidDataSource = (DruidDataSource)applicationContext.getBean("dataSource");
    DruidPooledConnection connection = druidDataSource.getConnection();
    System.out.println("通过Spring容器获取的connection"+connection);
    connection.close();
}

3 Spring集成Junit

Spring集成Junit步骤

① 导入依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>

② 使用**@Runwith注解替换原来的运行期
③ 使用
@ContextConfiguration指定配置文件或配置类
④ 使用
@Autowired**注入需要测试的对象
⑤ 创建测试方法进行测试

package com.raphuscucullatus.test;

import com.raphuscucullatus.config.SpringConfiguration;
import com.raphuscucullatus.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.sql.DataSource;
import java.sql.SQLException;


/**
 * spring集成junit测试用例
 *
 * @author raphus cucullatus
 * @version 2021/9/19 0:26
 * @since JDK8
 */
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration(classes = {SpringConfiguration.class})
public class TestUtil {
    @Autowired
    private UserService userService;
    @Autowired
    private DataSource dataSource;

    @Test
    public void test(){
//        userService.save();
        try {
            System.out.println(dataSource.getConnection());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值