spring ioc和注解

spring第二天ioc和注解

一、学习目标

  1. 掌握外部属性文件注入
  2. 掌握半xml半注解方式开发模式(必须掌握)
  3. 掌握全注解方式开发模式
  4. 掌握spring跟junit测试适配

二.外部属性文件注入

在实际开发中我们通常会有数据库连接账号密码 redis连接池账号密码 秘钥之类的属性需要配置

例如我们的数据库连接池配置

<!-- 导入mysql驱动包的依赖 --> 	
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.46</version>
</dependency>  
<!-- 导入druid连接池的依赖 --> 	
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.9</version>
</dependency>
<!-- 导入hikari的依赖 -->
<dependency>
    <groupId>hikari-cp</groupId>
    <artifactId>hikari-cp</artifactId>
    <version>1.7.6</version>
</dependency>

2.1最原始的配置

<!--
        配置druid的数据库连接池
        功能最全的 性能也牛逼的
    -->
    <bean id="dataSource0" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/heima29"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

    <!--hikari数据连接池  据说性能之王-->
    <bean id="dataSource1" class="com.zaxxer.hikari.HikariDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/heima29"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

上述配置自然是没有问题 但是有个缺点就是 讲属性配置到了spring的核心配置文件中 不容易查找和维护

2.2使用外部属性注入的方式

2.2.1 先创建一个外部属性文件 放在resources目录下
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/heima29
jdbc.username=root
jdbc.password=123456
2.2.2 在spring的配置文件修改外部属性注入
<!--
 配置外部properties属性位置信息
        classpath: 类路径的意思
-->
<context:property-placeholder location="classpath:db.properties"/>

<!--
	下方使用属性的方式 可以使用${属性名的方式}
-->

<bean id="dataSource0" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

<bean id="dataSource1" class="com.zaxxer.hikari.HikariDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

可以看出这种方式 维护更加自由 需要修改数据库配置的 不用打开xml配置文件 直接找到db.properties就行了

三、掌握半xml半注解方式开发模式(学习springboot之前都是这么玩的)

通过上述的学习过程中,我们可以在spring的配置文件中 配置我们业务需要的对象

<!--
        配置外部properties属性位置信息
        classpath: 类路径的意思
 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"></property>
</bean>

<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
    <property name="dataSource" ref="dataSource0"></property>
</bean>

<bean id="dataSource0" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>
<!--
	随着业务的开发 我们会在spring配置文件 
	配置越来越多的bean标签
-->
<bean id="xx" class="a.b.c.x">
<bean id="yy" class="a.b.c.y">
<bean id="zz" class="a.b.c.z">
.......       

这种方式最终会导致spring配置文件的膨胀 查找和维护工作十分费力

❤️接下来我们学习半xml半注解的方式 来做ioc配置 简化开发❤️

3.1 首先修改配置配置文件

<!--
    通过包扫描的方式 告诉spring框架 我的东西都在哪个包下放着呢
    多个包 以,分割开来
    所谓包扫描 原理就是找到那个文件遍历文件夹 查找这个文件夹的所有的文件名
  -->
<context:component-scan base-package="com.itheima.service,com.itheima.dao"/>
<!--
	注意事项:
	先保留下来 一些不是我们写的类 比如连接池对象之类 因为那些类不是我们写的
-->

3.2 修改代码 添加注解

service代码

package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.pojo.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
 *
 * 这里我们可以采用@Component注解或者@Service 注解
 * 建议使用@Service 注解 更加见名知意
 * 而且可以起名字 默认不写就是类名
 */
//@Component
@Service("AccountServiceImpl")
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;


    @Override
    public void save(Account account) {
        accountDao.save(account);
    }

    @Override
    public Account findById(int id) {

        return accountDao.findById(id);
}

    @Override
    public void update(Account account) {
        accountDao.update(account);
    }

    @Override
    public void del(int id) {
        accountDao.del(id);
    }
}

dao代码

package com.itheima.dao.impl;


import com.itheima.dao.AccountDao;
import com.itheima.pojo.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 *
 * 这里我们可以采用@Component注解或者@Repository 注解
 * 建议使用@Repository注解 更加见名知意
 * 而且可以起名字
 */
//@Component
@Repository("AccountDaoImpl")
public class AccountDaoImpl implements AccountDao {
    /*@Autowired
    @Qualifier("dataSource1")*/
    @Resource(name="dataSource1")
    private DataSource dataSource;

    @Override
    public void save(Account account) {
        System.out.println("保存账户信息");
    }

    @Override
    public Account findById(int id) {
        System.out.println("正在根据id查询账户信息");
        try {
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return new Account();
    }

    @Override
    public void update(Account account) {
        System.out.println("正在更新账户信息");
    }

    @Override
    public void del(int id) {
        System.out.println("正在根据id删除账户信息");
    }
}

测试代码

@Test
public void test01() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    AccountService accountService = context.getBean(AccountService.class);

    accountService.findById(1);
}

3.3常用的注解

3.3.1@Component(value="")注解

  1. 标记在类上,也可以放在接口上

  2. 注解作用:把AccountDao实现类对象交由Spring IOC容器管理

    • 相当于XML配置文件中的Bean标签

      <bean id="accountDao" class="com.itheima.dao.AccountDao"/>
      
  3. 注解Value属性:相当于bean标签id,对象在IOC容器中的唯一标识,可以不写,默认值是当前类首字母缩写的类名。

  4. 三个衍射注解分别是:@Controller,@Service,@Repository。

    • 作用与@Component注解一样
    • 设计初衷增加代码的可读性,体现三层架构
      • @Controller一般标注在表现层
      • @Service一般标注在业务层
      • @Repository一般 标注在持久层
  5. ❤️注意事项:

    组件可以起名 但是建议不要起名 它的默认名字就是类名 首字母小写

3.3.2@Autowired注解
  1. 标记在成员变量或set方法上

  2. 注解作用:自动将ioc容器中的对象注入到当前的成员变量中。

    • 默认按照变量数据类型注入,如果数据类型是接口,注入接口实现类。

    • 相当于XML配置文件中的property标签

      <property name="accountDao" ref="accountDao"/>
      
  3. 按照变量的数据类型注入

  4. 注意事项:

    • 它只能注入其他的bean类型
    • 成员变量的接口数据类型,有多个实现类的时候,要使用bean的id注入,否则会报错。
    • Spring框架提供的注解
  5. 指定Bean的id,使用@Qualifier的注解配合,@Qualifier注解的value属性指定bean的id

3.3.3@Resource(name="")注解

  1. 标记在成员变量或set方法上

  2. 注解作用:相当于@Autowired的注解与@Qualifier的注解合并了。直接按照bean的id注入。

    • 相当于XML配置文件中的property标签

      <property name="accountDao" ref="accountDao"/>
      
  3. name属性:指定bean的id

  4. 如果不写name属性则按照变量数据类型注入,数据类型是接口的时候注入其实现类。如果定义name属性,则按照bean的id注入。

  5. Java的JDK提供本注解

四、掌握全注解方式开发模式

4.1 复制上面的半xml半注解的代码 将配置文件删除

4.2 编写注解配置类

package com.itheima.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.itheima.pojo.User;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;

import javax.sql.DataSource;

/**
 *  @Configuration 这个注解意思 表示 该类就替代了beans.xml
 *  @ComponentScan 作用等同于<context:component-scan  base-package= "com.itheima.service,com.itheima.dao"></context:component-scan>
 *  @PropertySource 作用等同于 <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
 *
 * @Import 导入其他的配置类 分模块配置 便于维护
 *
 */
@Configuration
@ComponentScan({"com.itheima.service","com.itheima.dao"})
@Import({DataSourceConfig.class})
public class SpringConfig {
    /*我想放一个user对象进去行不行?*/
   /* @Bean
    public User xxx(){
        return new User();
    }*/

}

package com.itheima.config;


import com.alibaba.druid.pool.DruidDataSource;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
@PropertySource("classpath:db.properties")
public class DataSourceConfig {
    @Value("${jdbc.driverClassName}")
    private String className;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    /**
     * @Bean
     * 表示就该方法的返回值 放入到容器里 名字自己起名
     * 万一你忘记起名字 或者你对名字不敏感 它有默认名字 默认名字就是方法名字
     * @return
     */
    @Bean("dataSource0")
    public DataSource createDruidDatasource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(className);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
    @Bean("dataSource1")
    public DataSource createHikariDatasource(){
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setDriverClassName(className);
        hikariDataSource.setJdbcUrl(url);
        hikariDataSource.setUsername(username);
        hikariDataSource.setPassword(password);
        return hikariDataSource;
    }
}

4.3 纯注解开发IOC需要的注解

无XML配置文件beans.xml

4.3.1@Configuration注解

标记在类上

注解作用:作用等同于beans.xml配置文件,当前注解声明的类中,编写配置信息,所以我们把@Configuration声明的类称之为配置类

4.3.2@Import注解

标记在类上

注解作用:导入其他配置类(对象)

相当于XML配置文件中的标签

<import resource="classpath:applicationContext-dao.xml"/>
4.3.3@PropertySource注解

标记在类上

注解作用:引入外部属性文件(db.properties)

相当于XML配置文件中的context:property-placeholder标签

<context:property-placeholder location="classpath:jdbc.properties"/>
4.3.4@Value注解

标记在成员变量或set方法上,有点类似于@Autowired

注解作用:给简单类型变量赋值

相当于XML配置文件中的标签

<property name="driverClass" value="${jdbc.driver}"/>
4.3.5@Bean注解

标记在配置类中的方法上

注解作用:将方法的返回值存储到Spring IOC容器中

相当于XML配置文件中的标签

<bean id="accountDao" class="com.itheima.dao.AccountDaoImpl"/>
4.3.6@ComponentScan(“com.itheima”)注解

标记在配置类上

注解作用:扫描注解,相当于beans.xml中的注解扫描配置<context:component-scan base-package="com.itheima"/>

相当于XML配置文件中的context:component-scan标签

<context:component-scan base-package="com.itheima"/>

注意:扫描的包路径不写,扫描当前包及其子包!

其他了解的注解

@Scope(“prototype”)

标记在类上,配合@Component使用

注解作用:指定对象的作用范围:单例模式(singleton)还是多例模式(prototype)

生命周期注解

@PostConstruct ==> init-method

@PreDestroy ==> destroy-method

五、掌握spring跟junit测试适配

5.1 导入maven依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.7.RELEASE</version>
</dependency>
<!-- junit版本至少是4.12以上-->
<!-- junit版本至少是4.12以上-->
<!-- junit版本至少是4.12以上-->
<!-- junit版本至少是4.12以上-->
<!-- junit版本至少是4.12以上-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

5.2 编写测试类

package com.itheima;

import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * spring 想好了 已经封装了
 */

@RunWith(SpringJUnit4ClassRunner.class)
///xml方式用这个
@ContextConfiguration(locations = "classpath:beans.xml")
//注解方式用这个
//@ContextConfiguration(classes = SpringConfig.class)
public class App1Test {
    @Autowired
    private UserService userService;

    @Test
    public void test01() {
        userService.login("zhansgan","123");
    }
    @Test
    public void test02() {
        userService.save(new User());
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃娃 哈哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值