- Managing Third-Party Beans with IoC/DI Configuration
=======================================================
This section demonstrates how to manage third-party beans using Spring's Inversion of Control (IoC) container. We'll use DruidDataSource and ComboPooledDataSource as examples.
1.1 Managing a Data Source Object
1.1.1 Environment Setup
- Add Spring dependencies to
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
- Create a Spring configuration file:
<?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">
</beans>
- Create the application class:
package priv.dandelion;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
1.1.2 Implementation Steps
- Add the
druid dependency:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
- Configure the
DruidDataSource bean in the Spring configuration file:
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
- Retrieve the bean from the IoC container:
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource);
}
}
1.1.3 Managing C3P0
- Add the
c3p0 dependency:
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
- Configure the
ComboPooledDataSource bean:
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="user" value="root"/>
<property name="password" value="123456"/>
</bean>
- Add the MySQL driver dependency:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
1.2 Loading Properties Files
1.2.1 Implementation Steps
- Enable the
context namespace in the configuration:
<?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">
- Load the properties file:
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
- Use placeholders to inject properties:
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
1.2.2 Complete Code
<?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">
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=123456
- Core Container
=================
2.1 Environment Setup
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
BookDao interface and implementation not shown
- Spring configuration:
<?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="bookDao" class="priv.dandelion.dao.impl.BookDaoImpl"/>
</beans>
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
2.2 Container Creation
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
- Loading from file system:
ApplicationContext ctx = new FileSystemXmlApplicationContext("/absolute/path/to/config.xml");
ApplicationContext ctx = new ClassPathXmlApplicationContext("xml1.xml", "xml2.xml");
2.2.2 Retrieving Beans
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
BookDao bookDao = ctx.getBean("bookDao", BookDao.class);
BookDao bookDao = ctx.getBean(BookDao.class);
2.2.3 Lazy Initialization
public class AppForBeanFactory {
public static void main(String[] args) {
Resource resources = new ClassPathResource("applicationContext.xml");
BeanFactory bf = new XmlBeanFactory(resources);
BookDao bookDao = bf.getBean(BookDao.class);
bookDao.save();
}
}
- Lazy initialization in
ApplicationContext:
<bean id="bookDao" class="priv.dandelion.dao.impl.BookDaoImpl" lazy-init="true"/>
- Annotation-Based Development with Spring IoC/DI
==================================================
3.1 Environment Setup
- Spring dependencies
BookDao and BookService interfaces and implementations
- Spring configuration:
<?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">
</beans>
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) context.getBean("bookDao");
bookDao.save();
}
}
3.2 Defining Beans with Annotations
- Use
@Component to annotate classes:
@Component("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
- Enable component scanning:
<context:component-scan base-package="priv.dandelion"/>
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) context.getBean("bookDao");
bookDao.save();
BookService bookService = context.getBean(BookService.class);
System.out.println(bookService);
}
}
3.3 Pure Annotation-Based Configuration
- Create a configuration class:
@Configuration
@ComponentScan("priv.dandelion")
public class SpringConfig {
}
public class AppForAnnotation {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao) context.getBean("bookDao");
bookDao.save();
BookService bookService = context.getBean(BookService.class);
System.out.println(bookService);
}
}
3.4 Bean Scope and Lifecycle Management
- Set bean scope with
@Scope:
@Repository("bookDao")
@Scope("prototype")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
- Define lifecycle methods with
@PostConstruct and @PreDestroy:
@Repository("bookDao")
@Scope("singleton")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
@PostConstruct
public void init() {
System.out.println("book dao init ...");
}
@PreDestroy
public void destroy() {
System.out.println("book dao destroy ...");
}
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao) context.getBean("bookDao");
bookDao.save();
context.close();
}
}
3.5 Dependency Injection with Annotations
- Inject beans with
@Autowired:
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
- Inject by name with
@Qualifier:
@Service
public class BookServiceImpl implements BookService {
@Autowired
@Qualifier("bookDao")
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
- Inject simple values with
@Value:
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("dandelion")
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
- Load properties with
@PropertySource:
@Configuration
@ComponentScan({"priv.dandelion.dao","priv.dandelion.service"})
@PropertySource({"jdbc.properties","jdbc1.properties"})
public class SpringConfig {
}
- Managing Third-Party Beans with Annotations
==============================================
4.1 Environment Setup
- Spring dependencies
- Configuration class:
@Configuration
public class SpringConfig {
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
}
}
4.2 Managing Third-Party Beans
- Add the
druid dependency:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
- Use
@Bean to define beans:
@Configuration
@PropertySource("jdbc.properties")
public class SpringConfig {
@Bean
public DataSource dataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("${driverClassName}");
druidDataSource.setUrl("${url}");
druidDataSource.setUsername("${name}");
druidDataSource.setPassword("${password}");
return druidDataSource;
}
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}
4.3 External Configuration Classes
- Separate configuration into multiple classes:
@Configuration
@PropertySource("jdbc.properties")
public class JDBCConfig {
@Bean
public DataSource dataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("${driverClassName}");
druidDataSource.setUrl("${url}");
druidDataSource.setUsername("${name}");
druidDataSource.setPassword("${password}");
return druidDataSource;
}
}
- Import configuration classes:
@Configuration
@Import(JDBCConfig.class)
public class SpringConfig {
}
4.4 Injecting Resources into Third-Party Beans
@PropertySource("jdbc.properties")
public class JDBCConfig {
@Value("${driverClassName}")
private String driver;
@Value("${url}")
private String url;
@Value("${name}")
private String name;
@Value("${password}")
private String password;
@Bean
public DataSource dataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(name);
druidDataSource.setPassword(password);
return druidDataSource;
}
}
@Configuration
@ComponentScan("priv.dandelion.dao")
@Import(JDBCConfig.class)
public class SpringConfig {
}
@Bean
public DataSource dataSource(BookDao bookDao) {
System.out.println(bookDao);
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(name);
druidDataSource.setPassword(password);
return druidDataSource;
}
- Summary of Annotation-Based Developmant
==========================================
| Functionality |
XML Configuration |
Annotation |
| Bean Definition |
<bean> tag with id and class |
@Component, @Controller, @Service, @Repository with @ComponentScan |
| Dependency Injection |
Setter or constructor injection |
@Autowired, @Qualifier, @Value |
| Third-Party Beans |
<bean> tag with factory methods |
@Bean in configuration classes |
| Bean Scope |
scope attribute |
@Scope |
| Lifecycle |
init-method, destroy-method |
@PostConstruct, @PreDestroy |
- Integrating Spring with MyBatis and JUnit
============================================
6.1 Integrating MyBatis
6.1.1 Environment Setup
- Database schema and model class
- DAO interface with MyBatis annotations
- Service implementation annotated with
@Service
- Properties file for data base connection
- MyBatis configuration file
- Application class for testing
6.1.2 Integration Strategy
- Manage
SqlSessionFactory with Spring
- Use
SqlSessionFactoryBean to encapsulate configuration
- Use
MapperScannerConfigurer to scan DAO interfaces
6.2 Integration Steps
- Add dependencies for Spring-JDBC and MyBatis-Spring:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
- Create a configuration class:
@Configuration
@ComponentScan("priv.dandelion")
@PropertySource("classpath:jdbc.properties")
@Import(JDBCConfig.class)
public class SpringConfig {
}
- Create a MyBatis configuration class:
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("priv.dandelion.entity");
ssfb.setDataSource(dataSource);
return ssfb;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("priv.dandelion.dao");
return msc;
}
}
- Application class:
public class App2 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
AccountService accountService = ctx.getBean(AccountService.class);
Account account = accountService.findById(1);
System.out.println(account);
}
}
6.3 Integrating JUnit
6.3.1 Environment Setup
- Spring and MyBatis integration environment
6.3.2 Integration Steps
- Add JUnit and Spring test dependencies:
<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.2.10.RELEASE</version>
</dependency>
- Create a test class:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfig.class})
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Test
public void testFindById() {
System.out.println(accountService.findById(1));
}
@Test
public void testFindAll() {
System.out.println(accountService.findAll());
}
}
6.4 Related Annotations
| Annotation |
Description |
@RunWith |
Specifies the JUnit runner |
@ContextConfiguration |
Loads Spring configuration for testing |