Java开发Spring之IOC详解第二篇(注解开发JdbcTemplatem模板Junit整合)
Posted ahcfl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java开发Spring之IOC详解第二篇(注解开发JdbcTemplatem模板Junit整合)相关的知识,希望对你有一定的参考价值。
一、IOC相关注解
1、注解引入
<?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:component-scan base-package="packageName"/>
<beans/>
# 在spring配置文件中启动注解扫描,加载类中配置的注解项
<context:component-scan base-package="packageName"/>
- 说明:
在进行包所扫描时,会对配置的包及其子包中所有文件进行扫描
扫描过程是以文件夹递归迭代的形式进行的
扫描过程仅读取合法的java文件
扫描时仅读取spring可识别的注解
扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器
- 注意:
无论是注解格式还是XML配置格式,最终都是将资源加载到IoC容器中,差别是数据读取方式不同。
从加载效率上来说注解优于XML配置文件
2、bean实例化注解
# 这些注解使用在类上,用于创建被修饰的类对象,并将创建好的对象存放到IOC容器中
@Component : 组件
@Controller : 控制器
@Service : 服务
@Repository : 仓库
# 说明
@Component : (Component组件) 在类上使用该注解,把资源让spring来管理。
作用: 相当于bean标签,创建当前类对象并存放到IOC容器中
value属性: 指定bean的id,默认bean的id是当前类的类名。首字母小写。
@Controller,@Service,@Repository:
作用、使用、属性: 与@Component的作用和属性是一模一样的
他们只是提供了更加明确的语义化(见名知意),精确指出是哪一层的对象,但不是强制要求的
@Controller:一般用于表现层的注解。 将web层的类创建对象存放到IOC容器中
@Service:一般用于业务层的注解。 将serice层的类创建对象存放到IOC容器中
@Repository:一般用于持久层的注解。 将dao层的类创建对象存放到IOC容器中
# 以上注解相当于下面得到bean标签:
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"></bean>
代码演示:service层
//@Component
//@Controller
@Service
//@Repository
public class AccountServiceImpl implements AccountService {
@Override
public void add() {
System.out.println("add 方法执行了...");
}
}
3、数据注入的注解
`这些注解使用在属性上,用于给对象中的属性进行赋值:
@Autowired
@Qualifier
@Resource
@Value
`相当于xml中的set注入
<property name="userDao" ref="userDao" ></property>
<property name="userDao" value="基本类型数据或String"></property>
1)注入基本类型和String
@Value
`@Value:
作用:用于注入基本类型和String的注入
value属性: 指定数据的内容,它可以支持Spring的EL表达式(SPEL),写法:${表达式}
`SpEL表达式:
作用: 从IOC容器中获取对应的值
格式: ${key}
属性值来自于properties配置文件
`前提:
# 载properties配置文件中的信息存放到容器中
<context:property-placeholder
location="classpath:jdbc.properties"></context:property-placeholder>
`注意:
当我们使用注解注入数据时,构造器和set方法不是必须的了。
代码演示
xml配置
applicationContext.xml
<!--
注释: 写个程序员看的,当程序员看到注释后就明白了代码的含义
注解: 写给虚拟机看的,当虚拟机在编译代码时,根据不同的注解将代码编译成指定的格式
-->
<!-- 开启组件扫描: 告诉Spring框架,它的注解在哪个包中的类上 -->
<context:component-scan base-package="com.example"></context:component-scan>
<!-- 解析Properties配置文件,将配置文件中的数据加载到IOC容器中 -->
<context:property-placeholder
location="classpath:jdbc.properties"
file-encoding="utf-8">
</context:property-placeholder>
Properties配置
jdbc.username=root
jdbc.password=1234
jdbc.port=3306
service层
@Service("AccountService")
public class AccountServiceImpl1 implements AccountService {
/**
* @Value: 用于注入基本类型和String类型的数据
* Value注解可以使用SPEL表达式获取IOC容器中的数据 ${变量名称}
*/
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.port}")
private int port;
@Override
public void add() {
System.out.println("注入基本类型和String类型的数据.....");
System.out.println(username+" : "+password+" : "+port);
}
}
测试
package com.example.web;
public class AccountClient1 {
@Test
public void test01(){
//1.解析配置文件,得到ApplicationContext对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.调用应用上下文的API从IOC容器中获取bean对象
AccountService service = ac.getBean("AccountService", AccountService.class);
service.add();
}
}
2)注入bean类型
@Autowired
@Autowired: 默认按照bean的类型注入数据,如果类型相同,则按名称注入
`原理:
【被注入的对象,来自IOC容器】
(如果IOC容器中只有一个此类型的对象)-->直接注入
(如果IOC容器中有多个此类型的对象)-->按照IOC容器中对象的名称注入,如果名称不匹配错。
`属性:
required:
true: 此对象必须注入成功,若不成功则报错. 默认值
false: 可以注入不成功
@Qualifier
`作用:
与@Autowired注解一起使用,指定在按照bean类型注入的基础上,再按照bean的名称注入
`属性:
value:指定bean的名称
@Resource
此注解是JDK提供的,作用相当于 @Autowired+@Qualifier
`作用:
默认按照bean的名称注入数据,如果同一个接口有多个实现,可以通过指定属性进行注入
`属性:
name:指定bean的名称注入数据
type:指定bean的类型注入数据
`注意细节:
如果没有对应的名称与之匹配,则按照类型注入
代码演示
service层
package com.example.service.impl;
@Service("AccountService2")
public class AccountServiceImpl2 implements AccountService {
/**
* IOC容器:
* AccountDao:
* AccountDaoImpl name: accountDaoImpl
* AccountDaoImpl2 name: accountDaoImpl2
* type: AccountDao.class
* @Autowired: 将IOC容器中的对象注入到属性上
* 默认按照类型注入,当只有一个该类型对象时,直接注入
* 如果发现多个同类型的对象,则按照变量名称注入
* 如果没有一样的变量名则报错
* required属性: 是否必须注入成功(当前属性需要结合@Qualifier使用)
* true: 必须注入成功,否则报错 (默认值)
* false: 可以注入不成功,如果注入不成功,则为null
*
* @Qualifier: 指定注入的对象的名称
*
* @Resource:
* 默认按照名称注入,如果IOC容器中没有对应名称的对象,则按照类型注入
* type: 指定类型注入
* name: 指定名称注入
*/
//@Autowired(required = false)
//@Qualifier("accountDaoImpl2")
@Resource(type = AccountDao.class,name = "accountDaoImpl")
private AccountDao accountDao;
@Override
public void add() {
System.out.println("33333333333...");
accountDao.add();
}
}
dao层
package com.example.dao;
public interface AccountDao {
void add();
}
----------------------------------
package com.example.dao.impl;
import com.example.dao.AccountDao;
@Repository
public class AccountDaoImpl1 implements AccountDao {
@Override
public void add() {
System.out.println("AccountDaoImpl11111中的方法执行了");
}
}
-----------------------------------
package com.example.dao.impl;
import com.itheima.dao.AccountDao;
import org.springframework.stereotype.Repository;
@Repository
public class AccountDaoImpl2 implements AccountDao {
@Override
public void add() {
System.out.println("AccountDaoImpl22222中的方法执行了");
}
}
测试类
package com.example.web;
public class AccountClient2 {
@Test
public void test01(){
//1.解析配置文件,得到ApplicationContext对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.调用应用上下文的API从IOC容器中获取bean对象
AccountService service = ac.getBean("AccountService2", AccountService.class);
service.add();
}
}
4、bean作用范围与生命周期注解
1)作用范围注解
@Scope
@Scope:
作用: 用于调整bean的作用范围,相当于bean标签的scope属性
使用位置: 被创建的类上
value属性: 指定作用范围的取值。取值是固定的5个,和XML的配置取值是一样的。
singleton: 单实例 默认值
prototype: 多实例
2)生命周期注解
@PostConstruct
@PostConstruct : 热加载数据
作用: 指定初始化方法,相当于init-method
使用位置: 初始化的方法上
@PreDestroy
@PreDestroy : 资源回收
作用: 指定销毁方法,相当于destroy-method
使用位置: 销毁的方法上
3)代码演示
service层
package com.example.service.impl;
/**
* 测试作用范围
* @Scope:
* singleton: 单实例
* prototype: 多实例
* 生命周期:
* @PostConstruct: 设置初始化调用的方法
* @PreDestroy: 设置销毁前调用的方法
*/
@Service("AccountService3")
@Scope("prototype")
public class AccountServiceImpl3 implements AccountService {
@Override
public void add() {
System.out.println("AccountServiceImpl3 中的add方法执行了");
}
@PostConstruct
public void initMethod(){
System.out.println("对象初始化了...");
}
@PreDestroy
public void destoryMethod(){
System.out.println("对象销毁了...");
}
}
测试
package com.example.web;
import com.example.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountClient3 {
@Test
public void test01(){
//1.解析配置文件,得到ApplicationContext对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.调用应用上下文的API从IOC容器中获取bean对象
for (int i = 0; i < 10; i++) {
AccountService service = ac.getBean("AccountService3", AccountService.class);
System.out.println(service);
}
}
@Test
public void test02(){
//1.解析配置文件,得到ApplicationContext对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.调用应用上下文的API从IOC容器中获取bean对象
AccountService service = ac.getBean("AccountService3", AccountService.class);
System.out.println(service);
((ClassPathXmlApplicationContext) ac).close();
}
}
5、纯注解案例演示
使用配置类代替配置文件,将以下注解写在配置类上
@Configuration: 声明该类为Spring的配置文件类
@ComponentScan(basePackages = "com.example") : 指定要扫描的包
@PropertySource(value = "classpath:jdbc.properties") : 将配置文件交给Spring容器管理
@Bean() : 将方法返回的对象存放到IOC容器中,
将返回值存放到IOC容器中,一般将第三方提供的类对加载到IOC容器
1、@Configuration:声明配置类,代替applicationContext.xml的作用
2、@ComponentScan:配置注解扫描 ,这样注解才可以被识别
3、@Bean:将方法的返回值装配到IOC容器中
4、@PropertySource:加载外部资源文件
5、@Import:引入其他配置类
加载配置类,初始化IOC容器,获取工厂
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
@ComponentScan("com.example")
相当于
@ComponentScans(
{ @ComponentScan("com.example.web"),
@ComponentScan("com.example.service")
})
对比下面的applicationContext.xml配置
<!--相当于@ComponentScan 扫描包-->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!-- 相当于@PropertySource 读取外部根目录下资源配置文件-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--配置出druidDataSource数据源-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${dataSource.driverClassName}"></property>
<property name="url" value="${dataSource.url}"></property>
<property name="username" value="${dataSource.username}"></property>
<property name="password" value="${dataSource.password}"></property>
</bean>
<!--配置jdbc查询模板,注入druidDataSource数据源-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
SpringConfig类
package com.example.config;
@Configuration
@ComponentScan("com.example")
@PropertySource(value = "classpath:data.properties",encoding = "utf-8")
public class SpringConfig {
//@Bean("存放到IOC容器时的名称")【如果不设置名称,默认为当前方法的名称】
//将方法的返回值存放到IOC容器中
//@Bean("account")
@Bean
public Account getAccount(){
return new Account(1,"景甜",100f);
}
}
测试类
package com.example.web;
import com.example.config.SpringConfig;
import com.example.pojo.Account;
import com.example.service.AccountService;
public class AccountClient {
@Test
public void test01(){
//1.解析配置类,得到ApplicationContext对象
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
//2.调用应用上下文的API从IOC容器中获取bean对象
AccountService service = ac.getBean("AccountService", AccountService.class);
service.add();
}
@Test
public void test02(){
//1.解析配置类,得到ApplicationContext对象
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
//2.调用应用上下文的API从IOC容器中获取bean对象
Account account = ac.getBean("getAccount",Account.class);
System.out.println(account);
}
}
6、注解与xml对照表
注解 | xml | 说明 |
---|---|---|
@Component父注解 @Controller:用于表现层的注解 @Service:用于业务层的注解 @Repository:一般用于持久层的注解 | < bean id="" class=""> | 声明bean交于springIOC管理 |
@Scope | scope=“singleton/prototype” | 生命周期 |
@PostConstruct | init-method | 初始化方法 |
@PreDestroy | destroy-method | 销毁方法 |
@Autowired、@Qualifier @Resource | ref=“自定义类型” | 依赖注入 |
@Value | value=“基础数据类型” | 基本数据类型注入 |
二、JdbcTemplate【了解】
1、原生JDBC开发基本路程
package com.example.jdbc;
public class JdbcDemo {
public static void main(String[] args) throws Exception {
// 查询: 根据id查询,查询id为1的账户信息
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/itheima118_spring";
String username = "root";
String password = "root";
Connection conn = DriverManager
.getConnection(url, username, password);
//3.编写sql语句
String sql = "select * from account where id in (?,?) "<以上是关于Java开发Spring之IOC详解第二篇(注解开发JdbcTemplatem模板Junit整合)的主要内容,如果未能解决你的问题,请参考以下文章
JAVAWEB开发之Spring详解之——Spring的入门以及IOC容器装配Bean(xml和注解的方式)Spring整合web开发整合Junit4测试
Java之Spring入门到精通IDEA版IoC和DI注解开发(一篇文章精通系列)