目录

  • 1. 案例
  • 1.1 pom.xml文件
  • 1.2 .yml文件
  • 1.3 包结构
  • 1.4 代码
  • 1.4.1 新建包pojo下pojo类User类
  • 1.4.2 controller层
  • 1.4.3 service层实现类
  • 1.4.4 mapper层
  • 1.4.5 启动并访问测试
  • 2. 配置类与配置文件实现
  • 2.1 方式一:配置类形式
  • 2.1.1编辑配置类RedisConfig
  • 2.1.2修改UserServiceImpl
  • 2.2 方式二:xml文件形式
  • 2.2.1编辑applicationContext.xml
  • 2.2.2 修改UserServiceImpl
  • 3.ioc底层原理
  • 包结构
  • User
  • bean.properties
  • BeanFactory
  • 基础知识巩固:
  • 单元测试
  • 结果:


1. 案例

1.1 pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.tedu</groupId>
    <artifactId>ioctest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ioctest</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--Redis依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

1.2 .yml文件

server:
  port: 8082
  servlet:
    context-path: /

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root

mybatis:
  #别名包定义
  type-aliases-package: com.jt.pojo
  #引入映射文件
  mapper-locations: classpath:/mybatis/mappers/*.xml
  #开启驼峰映射 实现了字段与属性映射 自动去除"_" 并且之后的首字母大写
  configuration:
    map-underscore-to-camel-case: true

1.3 包结构

RedisTemplate 和 jedis_spring boot

1.4 代码

1.4.1 新建包pojo下pojo类User类
package com.tedu.pojo;

import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Value;
@Data
@Accessors(chain = true)
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String set;
}
1.4.2 controller层
package com.tedu.controller;

import com.tedu.pojo.User;
import com.tedu.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

//@Controller
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/findAll")
    public List<User> findAll(){
//        return userService.findAll();
        return userService.findCach();
    }
}
1.4.3 service层实现类
package com.tedu.service;

import com.tedu.config.RedisConfig;
import com.tedu.mapper.UserMapper;
import com.tedu.pojo.User;
import com.tedu.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserMapper userMapper;
//    @Autowired
//    private Jedis jedis;

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }

    @Override
    public List<User> findCach() {
        //创建对象的目的是为了获取类对象,不然userList.getClass()运行报错
        List<User> userList = new ArrayList<User>();
//        List<User> userList = null;
        String key = "userKey";
//        //层级耦合性太强,怎么解耦?
        Jedis jedis = new Jedis("192.168.74.128",6379);

        //改进1:ClassPathXmlApplicationContext“以XML为中心”的方式实例化容器
//        ClassPathXmlApplicationContext ac =
//                new ClassPathXmlApplicationContext("applicationContext.xml");
//        Jedis jedis = (Jedis) ac.getBean("jedis");

        //改进2:使用AnnotationConfigApplicationContext以Java中心的方式实例化容器
//        AnnotationConfigApplicationContext ctx =
//                new AnnotationConfigApplicationContext(RedisConfig.class);
//        Jedis jedis = ctx.getBean(Jedis.class);

        String value = jedis.get(key);

        if (StringUtils.isEmpty(value)) {
            //没有缓存,从数据库查询
            userList= findAll();
            //对象转JSON,并存到redis中
            value = ObjectMapperUtil.toJSON(userList);
            jedis.set(key,value);
            System.out.println("查询数据库并保存到redis中");
        }else {
            //缓存中有数据
            userList = ObjectMapperUtil.toObject(value,userList.getClass());
            System.out.println("redis缓存");
        }
        return userList;
    }
}
1.4.4 mapper层
package com.tedu.mapper;

import com.tedu.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserMapper {
    @Select("select * from user")
    List<User> findAll();
}
1.4.5 启动并访问测试

RedisTemplate 和 jedis_List_02


http://localhost:8082/findAll

RedisTemplate 和 jedis_List_03

2. 配置类与配置文件实现

2.1 方式一:配置类形式

2.1.1编辑配置类RedisConfig
package com.tedu.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;

//标识为配制类 与配置文件效果一样:xml <bean id="jedis"  class="redis.clients.jedis.Jedis"/>
@Configuration
public class RedisConfig {
    @Value("192.168.74.128")
    private String host;
    @Value("6379")
    private Integer port;

    @Bean//类似于bean标签
    public Jedis jedis(){
        return new Jedis(host,port);
    }
}
2.1.2修改UserServiceImpl

使用AnnotationConfigApplicationContext

RedisTemplate 和 jedis_spring boot_04

或者

使用@Autowired 自动装配

RedisTemplate 和 jedis_List_05

2.2 方式二:xml文件形式

2.2.1编辑applicationContext.xml
<?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-4.0.xsd">

    <!-- 声明bean对象,id是唯一标志,class:bean对象的全路径 -->
    <bean id="jedis" class="redis.clients.jedis.Jedis">
        <constructor-arg name="host" value="192.168.74.128"></constructor-arg>
        <constructor-arg name="port" value="6379"></constructor-arg>
    </bean>
</beans>
2.2.2 修改UserServiceImpl

使用ClassPathXmlApplicationContext

RedisTemplate 和 jedis_spring_06

3.ioc底层原理

摘自这篇文章


包结构

RedisTemplate 和 jedis_java_07

User

public class User {
    public void cc(){
        System.out.println("ioc底层实现");
    }
}

bean.properties

# bean.properties
aaa=com.example.pojo.User

BeanFactory

业务分析:
1.获取流对象
2.存入properties对象中
3.获取properties对象中的key、path
4.根据获得的path,反射创建对象
5.存入beans中(HashMap中)

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class BeanFactory {
    // 定义一个properties对象
    private static Properties props;

    // 定义一个Map,用于存放我们要创建的对象,我们将其称之为容器
    private static Map<String,Object> beans;

    // 使用静态代码块对Properties对象赋值
    static {
        try {
            // 实例化对象
            props = new Properties();

//            FileInputStream fileInputStream = new FileInputStream("D:/WorkSpaceIdea/demo1/javaee/test-ioc/src/main/resources/properties/bean.properties");
//            properties.load(fileInputStream);

            // 获取properties文件的流对象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            //用 load方法把读取的文件内容以键值对的方式传入properties对象中
            props.load(in);
            // 实例化容器
            beans = new HashMap<String,Object>();
            // 取出配置文件中所有的key
            Enumeration<Object> keys = props.keys();
            // 遍历枚举
            while (keys.hasMoreElements()){
                // 取出每个key
                String key = keys.nextElement().toString();
                // 根据key获取value
                String beanPath = props.getProperty(key);
                // 反射创建对象
                Object value = Class.forName(beanPath).newInstance();
                // 把bean放到容器中
                beans.put(key,value);
            }

        } catch (Exception e){
            e.printStackTrace();
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }

    /**
     * 根据bean的名称获取对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName) {
//        return beans.get(beanName);
        Object a = beans.get(beanName);
        return a;
    }
}
基础知识巩固:

1.一个全路径,一个类加载器相对路径

//getClass
	        InputStream resourceAsStream = beanFactory.getClass().getClassLoader().getResourceAsStream("properties/bean.properties");
			//类名.Class
            InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("properties/bean.properties");
			//全路径
            FileInputStream resourceAsStream = new FileInputStream("D:\\WorkSpaceIdea\\demo1\\javaee\\test-ioc\\src\\main\\resources\\properties\\bean.properties");

2.class.getClassLoader().getResourceAsStream与class.getResourceAsStream()区别?

3.下面两种书写都正确,区别在哪?

// 取出每个key
//                String key = keys.nextElement().toString();
                String key = (String) keys.nextElement();

4.java中类名.class, class.forName(), getClass()区别?


RedisTemplate 和 jedis_java_08


5.类方法与实例方法调用

RedisTemplate 和 jedis_List_09


RedisTemplate 和 jedis_List_10


6.回来研究

单元测试

package com.example;

import com.example.config.BeanFactory;
import com.example.pojo.User;
import org.junit.jupiter.api.Test;

public class Test1 {
    @Test
    public void test(){
        User user = (User) BeanFactory.getbean("aaa");
        user.cc();

    }
}

结果:

RedisTemplate 和 jedis_List_11