Java语言是c++语言的一个“纯净”版本,这里没有头文件,指针运算(甚至指针语法),结构,联合,操作符重载,虚基类等。
简单的另一个方面是小,Java的目标之一是支持开发能够在小型机器上独立运行的软件。
简单的讲,面向对象设计是一种程序设计技术,他将重点放在数据(即对象)和对象的接口上。
打个比喻:我(具有操作门的功能)去操作门(门有打开和关闭功能),把他打开,这就是面向对象
我走过去把门打开了,这是面向过程。
在本质上,Java的面向对象能力和c++是一样的,主要不同在于多继承(Java支持单继承(extends)多实现(implement)),在Java中取而代之的是简单的接口概念。
Java有一个扩展的例程库,用于处理像HTTP和FTP之类的TCP/IP协议。Java应用程序能够通过URL打开和访问网络上的对象,其便捷程度就好像访问本地文件一样。
Java的设计目标之一在于使得Java编写的程序具有多方面的可靠性。Java和c++最大的不同之处在于Java采用的指针模型可以消除重写内存和损坏数据的可能性。
Java编译器能够检测许多在其他语言中仅在运行时刻才能够检测出来的问题。
Java是绝对安全的,其原因是永远不会存取一个“坏的”指针,造成内存分配的错误,也不必防范内存泄漏。
Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。
Java适用于网络/分布式环境。
从一开始,Java就设计成能够防范各种攻击,其中包括:
运行时堆栈溢出,如蠕虫病毒等常用的攻击手段。
在自己 的处理空间之外破坏内存。
未经授权读写文件。
Java通过数字签名类,可以确定类的作者,如果信任这个类的作者,这个类就可以在你的机器上拥有更多的权限。
编译器生成一个体系结构中立的目标文件格式,这是一种编译过的代码,只要有Java系统运行时,就可以在许多处理器上运行。
Java编译器通过生成与特定的计算机体系结构无关的字节码指令来实现这一特性。
与c和c++不同,Java规范中没有“依赖具体实现”的地方。基本数据类型的大小以及有关算法都做了明确的说明。(例如Java中的int永远为32位的整数)
在Java中,数据类型具有固定的大小,这消除了代码移植时的问题。
二进制数据以固定的格式进行存储和传输。消除了字节顺序的困扰。字符串是用标准的Unicode格式存储的。
Java解释器可以在任何移植了解释器的机器上执行Java字节码。
尽管对解释后的字节码性能已经比较满意,但在有些场合下还需要更加高效的性能。 字节码可以(在运行时刻)快速的翻译成运行这个应用程序的特定CPU的机器码。性能就是“适应性更强”。
多线程可以带来更好的交互响应和实时行为。
Java中的线程可以利用多个处理器。
Java把多线程的实现交给了底层的操作系统或线程库来完成。
Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry和 Expiry。
Spring从3.1开始定义了org.springframework.cache.Cache 和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;
Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;
Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等;
每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
使用Spring缓存抽象时我们需要关注以下两点;
1、确定方法需要被缓存以及他们的缓存策略
2、从缓存中读取之前缓存存储的数据
Cache | 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、 ConcurrentMapCache等 |
---|---|
CacheManager | 缓存管理器,管理各种缓存(Cache)组件 |
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 |
@CacheEvict | 清空缓存 |
@CachePut | 保证方法被调用,又希望结果被缓存。 |
@EnableCaching | 开启基于注解的缓存 |
keyGenerator | 缓存数据时key生成策略 |
serialize | 缓存数据时value序列化策略 |
案例
启动类
package com.mikey.cache;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@MapperScan(value = "com.mikey.cache.mapper")
@SpringBootApplication
@EnableCaching//开启缓存
public class Springboot01CacheApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01CacheApplication.class, args);
}
}
spring.datasource.url=jdbc:mysql://localhost:3306/spring_cache
spring.datasource.username=root
spring.datasource.password=root
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 驼峰命名
mybatis.configuration.multiple-result-sets-enabled=true
# 日志级别
logging.level.com.mikey.cache.mapper=debug
import com.mikey.cache.bean.Employee;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Component;
@Component
@Mapper
public interface EmployeeMapper {
@Select("select * from employee where id=#{id}")
public Employee getEmpById(Integer id);
@Update("update employee set lastName=#{lastName},email=#{email},gender=#{gender},d_id=#{d_id} where id=#{id}")
public void updateEmp(Employee employee);
@Delete("Delete from employee where id=#{id}")
public void deleteEmpById(Integer id);
@Insert("insert employee(lastName,email,gender,d_id) values(#{lastName},#{email},#{gender},#{dId}")
public void insertEmployee(Employee employee);
}
import com.mikey.cache.bean.Employee;
import com.mikey.cache.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class EmployeeService {
@Autowired
EmployeeMapper employeeMapper;
/**
* 将方法的运行结果进行缓存
* @param id
* @return
*/
// @Cacheable(cacheNames = "emp",key = "#id")
@Cacheable(cacheNames = "emp",condition = "#id>0",unless = "#result==null")
public Employee getEmp(Integer id){
System.out.println("查询"+id+"号员工");
Employee employee=employeeMapper.getEmpById(id);
return employee;
}
}
import com.mikey.cache.bean.Employee;
import com.mikey.cache.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@RequestMapping("/emp/{id}")
public Employee getEmployee(@PathVariable("id") Integer id){
return employeeService.getEmp(id);
}
}
原理
1、自动配置类;CacheAutoConfiguration
2、缓存的配置类 org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】 org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
3、哪个配置类默认生效:SimpleCacheConfiguration;
4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager
5、可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中;
将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法; CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字;
运行流程
运行流程:
@Cacheable:
1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;
(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。
2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;
key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;
SimpleKeyGenerator生成key的默认策略;
如果没有参数;key=new SimpleKey();
如果有一个参数:key=参数的值
如果有多个参数:key=new SimpleKey(params);
3、没有查到缓存就调用目标方法;
4、将目标方法返回的结果,放进缓存中
@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,
如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;
核心:
1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator
几个属性:
cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
key:缓存数据使用的key;可以用它来指定。默认是使用方法参数的值 1-方法的返回值
编写SpEL; #i d;参数id的值 #a0 #p0 #root.args[0]
getEmp[2]
keyGenerator:key的生成器;可以自己指定key的生成器的组件id
key/keyGenerator:二选一使用;
cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器
condition:指定符合条件的情况下才缓存;
,condition = "#id>0"
condition = "#a0>1":第一个参数的值》1的时候才进行缓存
unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
unless = "#result == null"
unless = "#a0==2":如果第一个参数的值是2,结果不缓存;
sync:是否使用异步模式
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.util.Arrays;
@Configuration
public class MyCacheConfig {
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator(){
return new KeyGenerator(){
@Override
public Object generate(Object target, Method method, Object... params) {
return method.getName()+"["+ Arrays.asList(params).toString()+"]";
}
};
}
}
/**
* @CachePut:既调用方法,又更新缓存数据;同步更新缓存
* 修改了数据库的某个数据,同时更新缓存;
* 运行时机:
* 1、先调用目标方法
* 2、将目标方法的结果缓存起来
*
* 测试步骤:
* 1、查询1号员工;查到的结果会放在缓存中;
* key:1 value:lastName:张三
* 2、以后查询还是之前的结果
* 3、更新1号员工;【lastName:zhangsan;gender:0】
* 将方法的返回值也放进缓存了;
* key:传入的employee对象 值:返回的employee对象;
* 4、查询1号员工?
* 应该是更新后的员工;
* key = "#employee.id":使用传入的参数的员工id;
* key = "#result.id":使用返回后的id
* @Cacheable的key是不能用#result
* 为什么是没更新前的?【1号员工没有在缓存中更新】
*
*/
@CachePut(/*value = "emp",*/key = "#result.id")
public Employee updateEmp(Employee employee){
System.out.println("updateEmp:"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
@CacheEvict:缓存清除
key:指定要清除的数据
allEntries = true:指定清除这个缓存中所有的数据
beforeInvocation = false:缓存的清除是否在方法之前执行
默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除
beforeInvocation = true:
代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
@CacheEvict(value="emp",beforeInvocation = true/*key = "#id",*/)
public void deleteEmp(Integer id){
System.out.println("deleteEmp:"+id);
//employeeMapper.deleteEmpById(id);
int i = 10/0;
}
// @Caching 定义复杂的缓存规则
@Caching(
cacheable = {
@Cacheable(/*value="emp",*/key = "#lastName")
},
put = {
@CachePut(/*value="emp",*/key = "#result.id"),
@CachePut(/*value="emp",*/key = "#result.email")
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}
@CacheConfig(cacheNames="emp"/*,cacheManager = "employeeCacheManager"*/) //抽取缓存的公共配置
@Service
public class EmployeeService {
简化Spring应用开发的一个框架;
整个Spring技术栈的一个大整合;
J2EE开发的一站式解决方案;
2014,martin fowler
微服务:架构风格(服务微化)
一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;
单体应用:ALL IN ONE
微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;