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管理
@Scopescope=“singleton/prototype”生命周期
@PostConstructinit-method初始化方法
@PreDestroydestroy-method销毁方法
@Autowired、@Qualifier
@Resource
ref=“自定义类型”依赖注入
@Valuevalue=“基础数据类型”基本数据类型注入

二、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测试

spring之IOC实现的其他方式

Java之Spring入门到精通IDEA版IoC和DI注解开发(一篇文章精通系列)

Java之Spring入门到精通IDEA版IoC和DI注解开发(一篇文章精通系列)

Spring总结四:IOC和DI 注解方式

Java开发Spring之IOC详解第一篇(xml开发常用APIben标签DI依赖注入)