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 包结构
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 启动并访问测试
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
或者
使用@Autowired 自动装配
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
3.ioc底层原理
摘自这篇文章
https://blog.csdn.net/weixin_44547562/article/details/106145686
包结构
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.下面两种书写都正确,区别在哪?
https://blog.csdn.net/qq924862077/article/details/48022185
// 取出每个key
// String key = keys.nextElement().toString();
String key = (String) keys.nextElement();
4.java中类名.class, class.forName(), getClass()区别?
https://blog.csdn.net/jdnicky/article/details/92657628
5.类方法与实例方法调用
6.回来研究
https://blog.csdn.net/u014207665/article/details/84885422
单元测试
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();
}
}