1 Spring Configuration Data Source
1.1 Role of data sources (connections)
- Data sources (connection pools) are available to improve program performance
- Pre-instantiate the data source to initialize partial connection resources
- Get from data source when using connection resources
- Return the connected resource to the data source after use
Common data sources (connection pools): DBCP, C3P0, BoneCP, Druid, etc.
1.2 Steps to develop data sources
Manual creation of data sourcesDatabase Data Source Dependency
<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>
Test Class
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 Druid Data Source Test Class * * @author raphus cucullatus * @version 2021/9/18 1:03 * @since JDK8 */ public class DataSourceTest { /** * Manually configure connection parameters to create a c3p0 data source */ @Test public void testManualCreateDataSource() throws Exception { //create data source ComboPooledDataSource dataSource = new ComboPooledDataSource(); //Setting database connection parameters dataSource.setDriverClass("com.mysql.cj.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://127.168.2.8:3306/jdbc"); dataSource.setUser("root"); dataSource.setPassword("088.5741"); //Get Connection Object Connection connection = dataSource.getConnection(); System.out.println(connection); } /** * Manually configure connection parameters to create Druid data sources */ @Test public void testManualCreateDruidDataSource() throws SQLException { //create data source DruidDataSource dataSource = new DruidDataSource(); //Setting database connection parameters dataSource.setPassword("root"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/jdbc"); dataSource.setUsername("root"); dataSource.setPassword("088.5741"); //Get Connection Object Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); } /** * Create c3p0 data source by reading configuration file */ @Test public void testCreateDataSource() throws PropertyVetoException, SQLException { //jdbc.properties under load class path ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc"); ComboPooledDataSource dataSource = new ComboPooledDataSource(); //Read profile information using 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(); } /** * Create Druid Data Source by Reading Configuration File */ @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 data source profile
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/jdbc jdbc.username=root jdbc.password=088.5741
druid data source profile
url=jdbc:mysql://127.0.0.1:3306/jdbc username=root password=088.5741 maxActive=20 initialSize=5 maxWait=6000 asyncInit=true
Decouple data source development from hard coding to configuration files
1.3 Spring Configuration Data Source
In addition to the database data source dependency of the response, you also import the spring dependency
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
Configure spring Core Profile
<?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"> <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>
test
/** * Generating a c3p0 data source from a spring container */ @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("adopt spring Container acquired connection:"+connection); connection.close(); }
1.4 Spring Extraction Profile
Data Source Profile Information
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/jdbc jdbc.username=root jdbc.password=088.5741
spring Core Profile
Note: Attribute contenxt namespace needs to be added inside the beans tag (add in bold section below)
<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"
>
And add the following subtags inside the beans to bring in the external properties file (where the location property is the path of the external 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" > <!-- Loading external properties file --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- Use spring Expression acquisition properties Value in file --> <bean id="dataSource"> <property name="driverClass" value="$"></property> <property name="jdbcUrl" value="$"></property> <property name="user" value="$"></property> <property name="password" value="$"></property> </bean> <bean id="druidDataSource"> <property name="url" value="$"></property> <property name="username" value="$"></property> <property name="password" value="$"></property> </bean> </beans>
Test Code
/** * Generating a c3p0 data source from a spring container */ @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("adopt spring Container acquired connection:"+connection); connection.close(); } /** * Generating Druid Data Source from spring Container */ @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("adopt Spring Container acquired connection"+connection); connection.close(); }
2 Spring Annotation Development
2.1 Quick Start Notes
Reduce my configuration and improve development efficiency with the following original comments
Case study: Replace xml configuration with Component and Autowired Qualifier
spring Core Profile:
<!-- Configure Component Scan --> <context:component-scan base-package="com.raphuscucullatus"/>
Dao Layer
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")//Equivalent to <bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl"/> public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("save running...."); } }
Service Layer
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 Implementation Class * * @author raphus cucullatus * @version 2021/9/17 20:42 * @since JDK8 */ @Component("userService")//Equivalent to <bean id="userService" class="com.raphuscucullatus.service.impl.UserServiceImpl"/> public class UserServiceImpl implements UserService { /** * set injection * @param userDao */ @Autowired @Qualifier("userDao")//Equivalent to set injection <property name="userDao" ref="userDao"/> private UserDao userDao; public void setUserDao(UserDao userDao){ this.userDao=userDao; } @Override public void save() { userDao.save(); } }
test
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; /** * Simulate test cases for the control layer * * @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 Detailed original notes
Core Profile
**Note: ** You need to use the context namespace (added in the properties of the beans tag)
<?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" > <!-- Loading external properties file --> <context:property-placeholder location="jdbc.properties"/> <!-- Configure Component Scan(Do not configure package scanning,spring Classes that need to be injected will not be recruited) --> <context:component-scan base-package="com.raphuscucullatus"/> </beans>
Using annotations in the dao layer
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")//Equivalent to <bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl"/> @Repository("userDao")//Equivalent to @Component("userDao") and indicates that the class is a dao layer class public class UserDaoImpl implements UserDao { /** * User name */ //Same as <property name="user" value="$"></property> @Value("$")//Read the value of the external properties file through the annotation configuration private String userName; /** * Password */ //Same as <property name="password" value="$"></property> @Value("$")//Read the value of the external properties file through the annotation configuration private String password; @PostConstruct//Execute the send method after executing the constructor (Understanding) public void init (){ System.out.println("UserDaoImpl Initialization"); } @PreDestroy//Execute before destroying containers (Understanding) public void destroy (){ System.out.println("UserDaoImpl Destroyed"); } @Override public void save() { System.out.println("User name:"+userName+",Password:"+password); System.out.println("save running...."); } }
Using annotations in the service layer
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 Implementation Class * * @author raphus cucullatus * @version 2021/9/17 20:42 * @since JDK8 */ //@Component("userService")//Equivalent to <bean id="userService" class="com.raphuscucullatus.service.impl.UserServiceImpl"/> @Service("userService")//Equivalent to @Component("userService") at service level @Scope("singleton") public class UserServiceImpl implements UserService { /** * set injection * @param userDao */ // When @Autowired//does not use the @Qualifier("userDao") annotation, the default matching data type (.class) is injected, and the @Qualifier("userDao") annotation must be used if there are multiple types of the same type in the container // @Qualifier("userDao")// Equivalent to set injection <property name="userDao" ref="userDao"/>, @Qualifier must be used with @Autowired @Resource(name="userDao")//Equivalent to @Qualifier+@Autowired private UserDao userDao; //This set method may not be defined when using annotation configuration // public void setUserDao(UserDao userDao){ // this.userDao=userDao; // } @Override public void save() { userDao.save(); } }
Simulate test cases for the control layer
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; /** * Simulate test cases for the control layer * * @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 New Notes Detailed
Solve the original annotation problem
The xml configuration file cannot be completely replaced, and the following configuration needs to be replaced by annotations:
- Configuration of non-custom beans:
- Load the configuration of the properties file: context:property-placeholder
- Configuration for component scanning: context:component-scan
- Introduce additional core profile files:
<?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" > <!-- Non-Custom Bean Configuration --> <bean id="dataSource"> <property name="driverClass" value="$"></property> <property name="jdbcUrl" value="$"></property> <property name="user" value="$"></property> <property name="password" value="$"></property> </bean> <!-- Loading external properties file --> <context:property-placeholder location="jdbc.properties"/> <!-- Configure Component Scan(Do not configure package scanning,spring Classes that need to be injected will not be recruited) --> <context:component-scan base-package="com.raphuscucullatus"/> <!-- Introducing external profiles --> <import resource="applicationContext-user.xml"/> </beans>
Core Configuration Class
Do not introduce external configuration
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 Core Configuration Class * * @author raphus cucullatus * @version 2021/9/18 23:10 * @since JDK8 */ @Configuration//Tell Spring configuration information to look into this class (that is, use this class instead of the configuration file) @ComponentScan("com.raphuscucullatus")//Same: <context:component-scan base-package="com.raphuscucullatus"/> @PropertySource("jdbc.properties")//Same: <context:property-placeholder location="jdbc.properties"/> //@Import()//Same: <import resource="applicationContext-user.xml"/> public class SpringConfiguration { @Value("$") private String jdbcUrl; @Value("$") private String user; @Value("$") private String password; @Bean("dataSource") // <bean id="dataSource"> // <property name="driverClass" value="$"></property> // <property name="jdbcUrl" value="$"></property> // <property name="user" value="$"></property> // <property name="password" value="$"></property> // </bean> // For non-custom classes, the @Component("dataSource") annotation cannot be added to their source code, the solution is as follows: @Bean() public DataSource getDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(jdbcUrl); dataSource.setUsername(user); dataSource.setPassword(password); return dataSource; } }
Introducing external configuration
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 Core Configuration Class * * @author raphus cucullatus * @version 2021/9/18 23:10 * @since JDK8 */ @Configuration//Tell Spring configuration information to look into this class (that is, use this class instead of the configuration file) @ComponentScan("com.raphuscucullatus")//Same: <context:component-scan base-package="com.raphuscucullatus"/> @PropertySource("jdbc.properties")//Same: <context:property-placeholder location="jdbc.properties"/> @Import()//<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; /** * Data Source Configuration Class * @author raphus cucullatus * @version 2021/9/18 23:46 * @since JDK8 */ public class DataSourceConfiguration { @Value("$") private String jdbcUrl; @Value("$") private String user; @Value("$") private String password; @Bean("dataSource") public DataSource getDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(jdbcUrl); dataSource.setUsername(user); dataSource.setPassword(password); return dataSource; } }
This test class can be tested in both ways
/** * Generating Druid Data Sources by Configuring spring Containers with Annotations */ @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("adopt Spring Container acquired connection"+connection); connection.close(); }
3 Spring Integrated Junit
Spring Integrated Junit Step
1. Import Dependency
<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>
(2) Replace the original run time with the **@Runwith comment
(3) Use @ContextConfiguration to specify profiles or configuration classes
(4) Use @Autowired** to inject objects that need to be tested
Create test methods for testing
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 Integrated junit test cases * * @author raphus cucullatus * @version 2021/9/19 0:26 * @since JDK8 */ @RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration("classpath:applicationContext.xml") @ContextConfiguration(classes = ) 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(); } } }