动态代理模式_应用(Redis工具类)
本次使用动态代理的初衷是学习Redis,使用Java操作Redis时用到Jedis的JedisPool,而后对Jedis的方法进一步封装完善成为一个工具类。
因为直接使用Jedis对象时,为了保证性能,总会需要手动的获取到连接池中的连接,使用完成后还需要手动的释放连接,都是完全重复的操作。
所以想要使用一些方法来抽取出这些重复操作,初时想到的是使用模板方法或是动态代理,但考虑到到模板方法会使用到大量的类,似乎与主旨不符,遂使用动态代理进行加强。
实现动态代理可使用JDK对应的方法,或是CGlib。由于工具类本身不会去定义接口,所以选择CGlib。本身是在SpringBoot项目中进行,所以没有额外导入CGlib的包(spring的面向切面就使用到了CGlib与JDK自带的动态 代理)。
具体的思路就是使用动态代理来增强工具类对象,使得工具类在调用方法前后对应的进行获取连接及释放连接操作。在获得到增强工具类后只需要进行相关操作即可。
使用了Maven来管理项目,代码所需的依赖如下
<!-- Jedis -->
<dependency>
<groupId>com.redislabs</groupId>
<artifactId>jredisearch-jedis</artifactId>
<version>3.0.0-20180508</version>
</dependency>
此外还需要自己电脑安装Redis,或有对应的服务器
代码如下
Redis连接池代码
package com; import org.apache.logging.log4j.Logger; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Jedis连接池
*
* @author zaizouGGG
*
*/
public class RedisPool { private Logger logger = LogUtil.get(JedisUtil.class);
private static SysConfigUtil sysConfigUtil = SysConfigUtil.getSysConfigUtil("redis.properties"); //声明成static的原因:保证jedis连接池在tomcat启动时就加载出来
//jedis连接池
private static JedisPool pool;
//与redis连接池连接的最大连接数
private static Integer maxTotal = sysConfigUtil.getInt("redis.maxTotal");
//在jedis连接池中最大的idle状态(空闲的)的jedis实例的个数
private static Integer maxIdle = sysConfigUtil.getInt("redis.maxIdle");
//在jedis连接池中最小的idle状态(空闲的)的jedis实例的个数
private static Integer minIdle = sysConfigUtil.getInt("redis.minIdle");
//在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则得到的jedis实例肯定是可用的
private static Boolean testOnBorrow = sysConfigUtil.getBoolean("redis.testOnBorrow");
//在return一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则返回jedis连接池的jedis实例肯定是可用的
private static Boolean testOnReturn = sysConfigUtil.getBoolean("redis.testOnReturn");
private static String redisIp = sysConfigUtil.getString("redis.host");
private static Integer redisPort = sysConfigUtil.getInt("redis.port");
private static String password = sysConfigUtil.getString("redis.password"); //初始化连接池,只会调用一次
private static void initPool() {
JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle); config.setTestOnBorrow(testOnBorrow);
config.setTestOnReturn(testOnReturn); //连接池耗尽的时候,是否阻塞,false会抛出异常,true阻塞直到超时,会抛出超时异常,默认为true
config.setBlockWhenExhausted(true); //这里超时时间是2s
if (password != null && !"".equals(password)) {
// redis 设置了密码
pool = new JedisPool(config, redisIp, redisPort, 1000*2, password);
} else {
// redis 未设置密码
pool = new JedisPool(config, redisIp, redisPort, 1000*2);
}; } static {
initPool();
} //从连接池中拿取一个实例
public static Jedis getJedis() {
return pool.getResource();
} //返还Jedis
public static void returnJedis(Jedis jedis) {
jedis.close();
} //被使用的连接数
public static int getNumActive() {
return pool.getNumActive();
} //被阻塞的连接数?
public static int getNumWaiters() {
return pool.getNumWaiters();
} //空闲的连接数
public static int getNumIdle() {
return pool.getNumIdle();
}
}
读取.properties配置文件的工具类
用于读取配置在.properties中的参数
package com; import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties; import org.apache.logging.log4j.Logger; /**
* 获取自定义配置文件参数的共用方法
*
* @author zaizouGGG
*
*/
public class SysConfigUtil { private static Logger logger = LogUtil.get(SysConfigUtil.class);
private Properties properties = null; public SysConfigUtil() { } public SysConfigUtil(Properties p) {
properties = p;
} public static SysConfigUtil getSysConfigUtil(String url) {
try(InputStream in = new BufferedInputStream(new FileInputStream(url));) {
Properties p = new Properties();
p.load(in);
//return p.getProperty("jdbc.type");
return new SysConfigUtil(p);
} catch (IOException e) {
// TODO Auto-generated catch block
logger.error("Jedis工具类初始化失败,读取配置文件 "+url+" 出错");
e.printStackTrace();
return null;
} } public String getString(String key) {
return properties.getProperty(key);
} public int getInt(String key) {
int result = Integer.parseInt(properties.getProperty(key));
return result;
} public boolean getBoolean(String key) {
boolean result = Boolean.parseBoolean(properties.getProperty(key));
return result;
} public long getLong(String key) {
long result = Long.parseLong(properties.getProperty(key));
return result;
}
}
Redis配置文件
此处的配置是我从网上找的,普通的使用没有问题,要应用请慎重
redis.host=localhost
redis.port=6379
redis.password=root
#在指定时刻通过pool能够获取到的最大的连接的jedis个数
redis.maxTotal=8
#最大能够保持idle的数量,控制一个pool最多有多少个状态为idle的jedis实例
redis.maxIdle=8
#最小能够保持idle的数量,控制一个pool最多有多少个状态为idle的jedis实例
redis.minIdle=2
#在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则得到的jedis实例肯定是可用的
redis.testOnBorrow=true
#在return一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则返回jedis连接池的jedis实例肯定是可用的
redis.testOnReturn=false
#当连接池内的连接耗尽时,getBlockWhenExhausted为true时,连接会阻塞,超过了阻塞的时间(设定的maxWaitMillis,单位毫秒)时会报错
redis.maxWaitMillis=3000
#在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;默认是false
redis.testOnBorrow=false
Jedis的工具类
package com; import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set; import org.apache.logging.log4j.Logger; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.ListPosition; /**
* Jedis 通用工具类
* @author zaizouGGG
*
*/
public class JedisUtil { private Logger logger = LogUtil.get(JedisUtil.class);
private Jedis jedis = null; public Jedis getJedis() {
return jedis;
} public void setJedis(Jedis jedis) {
this.jedis = jedis;
} /**
* 获取指定key的值,如果key不存在返回null,如果该Key存储的不是字符串,会抛出一个错误
*
* @param key
* @return
*/
public String get(String key) {
String value = jedis.get(key);
return value;
} /**
* 设置key的值为value
*
* @param key
* @param value
* @return
*/
public String set(String key, String value) {
String result = jedis.set(key, value);
return result;
} /**
* 删除指定的key,也可以传入一个包含key的数组
*
* @param keys
* @return
*/
public Long del(String... keys) { return jedis.del(keys);
} /**
* 通过key向指定的value值追加值
*
* @param key
* @param str
* @return
*/
public Long append(String key, String str) { return jedis.append(key, str);
} /**
* 判断key是否存在
*
* @param key
* @return
*/
public Boolean exists(String key) { return jedis.exists(key);
} /**
* 设置key value,如果key已经存在则返回0
*
* @param key
* @param value
* @return
*/
public Long setnx(String key, String value) { return jedis.setnx(key, value);
} /**
* 设置key value并指定这个键值的有效期
*
* @param key
* @param seconds
* @param value
* @return
*/
public String setex(String key, String value, int seconds) {
String result = jedis.setex(key, seconds, value);
return result;
} /**
* 通过key 和offset 从指定的位置开始将原先value替换
*
* @param key
* @param offset
* @param str
* @return
*/
public Long setrange(String key, int offset, String str) { return jedis.setrange(key, offset, str);
} /**
* 通过批量的key获取批量的value
*
* @param keys
* @return
*/
public List<String> mget(String... keys) { return jedis.mget(keys);
} /**
* 批量的设置key:value,也可以一个
*
* @param keysValues
* @return
*/
public String mset(String... keysValues) { return jedis.mset(keysValues);
} /**
* 批量的设置key:value,可以一个,如果key已经存在则会失败,操作会回滚
*
* @param keysValues
* @return
*/
public Long msetnx(String... keysValues) { return jedis.msetnx(keysValues);
} /**
* 设置key的值,并返回一个旧值
*
* @param key
* @param value
* @return
*/
public String getSet(String key, String value) { return jedis.getSet(key, value);
} /**
* 通过下标 和key 获取指定下标位置的 value
*
* @param key
* @param startOffset
* @param endOffset
* @return
*/
public String getrange(String key, int startOffset, int endOffset) { return jedis.getrange(key, startOffset, endOffset);
} /**
* 通过key 对value进行加值+1操作,当value不是int类型时会返回错误,当key不存在是则value为1
*
* @param key
* @return
*/
public Long incr(String key) { return jedis.incr(key);
} /**
* 通过key给指定的value加值,如果key不存在,则这是value为该值
*
* @param key
* @param integer
* @return
*/
public Long incrBy(String key, long integer) { return jedis.incrBy(key, integer);
} /**
* 对key的值做减减操作,如果key不存在,则设置key为-1
*
* @param key
* @return
*/
public Long decr(String key) { return jedis.decr(key);
} /**
* 减去指定的值
*
* @param key
* @param integer
* @return
*/
public Long decrBy(String key, long integer) { return jedis.decrBy(key, integer);
} /**
* 通过key获取value值的长度
*
* @param key
* @return
*/
public Long strLen(String key) { return jedis.strlen(key);
} /**
* 通过key给field设置指定的值,如果key不存在则先创建,如果field已经存在,返回0
*
* @param key
* @param field
* @param value
* @return
*/
public Long hsetnx(String key, String field, String value) { return jedis.hsetnx(key, field, value);
} /**
* 通过key给field设置指定的值,如果key不存在,则先创建
*
* @param key
* @param field
* @param value
* @return
*/
public Long hset(String key, String field, String value) { return jedis.hset(key, field, value);
} /**
* 通过key同时设置 hash的多个field
*
* @param key
* @param hash
* @return
*/
public String hmset(String key, Map<String, String> hash) { return jedis.hmset(key, hash);
} /**
* 通过key 和 field 获取指定的 value
*
* @param key
* @param failed
* @return
*/
public String hget(String key, String failed) { return jedis.hget(key, failed);
} /**
* 设置key的超时时间为seconds
*
* @param key
* @param seconds
* @return
*/
public Long expire(String key, int seconds) { return jedis.expire(key, seconds);
} /**
* 通过key 和 fields 获取指定的value 如果没有对应的value则返回null
*
* @param key
* @param fields 可以是 一个String 也可以是 String数组
* @return
*/
public List<String> hmget(String key, String... fields) { return jedis.hmget(key, fields);
} /**
* 通过key给指定的field的value加上给定的值
*
* @param key
* @param field
* @param value
* @return
*/
public Long hincrby(String key, String field, Long value) { return jedis.hincrBy(key, field, value);
} /**
* 通过key和field判断是否有指定的value存在
*
* @param key
* @param field
* @return
*/
public Boolean hexists(String key, String field) { return jedis.hexists(key, field);
} /**
* 通过key返回field的数量
*
* @param key
* @return
*/
public Long hlen(String key) { return jedis.hlen(key);
} /**
* 通过key 删除指定的 field
*
* @param key
* @param fields 可以是 一个 field 也可以是 一个数组
* @return
*/
public Long hdel(String key, String... fields) { return jedis.hdel(key, fields);
} /**
* 通过key返回所有的field
*
* @param key
* @return
*/
public Set<String> hkeys(String key) { return jedis.hkeys(key);
} /**
* 通过key返回所有和key有关的value
*
* @param key
* @return
*/
public List<String> hvals(String key) { return jedis.hvals(key);
} /**
* 通过key获取所有的field和value
*
* @param key
* @return
*/
public Map<String, String> hgetall(String key) { return jedis.hgetAll(key);
} /**
* 通过key向list头部添加字符串
*
* @param key
* @param strs 可以是一个string 也可以是string数组
* @return 返回list的value个数
*/
public Long lpush(String key, String... strs) { return jedis.lpush(key, strs);
} /**
* 通过key向list尾部添加字符串
*
* @param key
* @param strs 可以是一个string 也可以是string数组
* @return 返回list的value个数
*/
public Long rpush(String key, String... strs) { return jedis.rpush(key, strs);
} /**
* 通过key在list指定的位置之前或者之后 添加字符串元素
*
* @param key
* @param where LIST_POSITION枚举类型
* @param pivot list里面的value
* @param value 添加的value
* @return
*/
public Long linsert(String key, ListPosition where,
String pivot, String value) { return jedis.linsert(key, where, pivot, value);
} /**
* 通过key设置list指定下标位置的value
* 如果下标超过list里面value的个数则报错
*
* @param key
* @param index 从0开始
* @param value
* @return 成功返回OK
*/
public String lset(String key, Long index, String value) { return jedis.lset(key, index, value);
} /**
* 通过key从对应的list中删除指定的count个 和 value相同的元素
*
* @param key
* @param count 当count为0时删除全部
* @param value
* @return 返回被删除的个数
*/
public Long lrem(String key, long count, String value) { return jedis.lrem(key, count, value);
} /**
* 通过key保留list中从strat下标开始到end下标结束的value值
*
* @param key
* @param start
* @param end
* @return 成功返回OK
*/
public String ltrim(String key, long start, long end) { return jedis.ltrim(key, start, end);
} /**
* 通过key从list的头部删除一个value,并返回该value
*
* @param key
* @return
*/
public synchronized String lpop(String key) { return jedis.lpop(key);
} /**
* 通过key从list尾部删除一个value,并返回该元素
*
* @param key
* @return
*/
synchronized public String rpop(String key) { return jedis.rpop(key);
} /**
* 通过key从一个list的尾部删除一个value并添加到另一个list的头部,并返回该value
* 如果第一个list为空或者不存在则返回null
*
* @param srckey
* @param dstkey
* @return
*/
public String rpoplpush(String srckey, String dstkey) { return jedis.rpoplpush(srckey, dstkey);
} /**
* 通过key获取list中指定下标位置的value
*
* @param key
* @param index
* @return 如果没有返回null
*/
public String lindex(String key, long index) { return jedis.lindex(key, index);
} /**
* 通过key返回list的长度
*
* @param key
* @return
*/
public Long llen(String key) { return jedis.llen(key);
} /**
* 通过key获取list指定下标位置的value
* 如果start 为 0 end 为 -1 则返回全部的list中的value
*
* @param key
* @param start
* @param end
* @return
*/
public List<String> lrange(String key, long start, long end) { return jedis.lrange(key, start, end);
} /**
* 通过key向指定的set中添加value
*
* @param key
* @param members 可以是一个String 也可以是一个String数组
* @return 添加成功的个数
*/
public Long sadd(String key, String... members) { return jedis.sadd(key, members);
} /**
* 通过key删除set中对应的value值
*
* @param key
* @param members 可以是一个String 也可以是一个String数组
* @return 删除的个数
*/
public Long srem(String key, String... members) { return jedis.srem(key, members);
} /**
* 通过key随机删除一个set中的value并返回该值
*
* @param key
* @return
*/
public String spop(String key) { return jedis.spop(key);
} /**
* 通过key获取set中的差集
* 以第一个set为标准
*
* @param keys 可以 是一个string 则返回set中所有的value 也可以是string数组
* @return
*/
public Set<String> sdiff(String... keys) { return jedis.sdiff(keys);
} /**
* 通过key获取set中的差集并存入到另一个key中
* 以第一个set为标准
*
* @param dstkey 差集存入的key
* @param keys 可以 是一个string 则返回set中所有的value 也可以是string数组
* @return
*/
public Long sdiffstore(String dstkey, String... keys) { return jedis.sdiffstore(dstkey, keys);
} /**
* 通过key获取指定set中的交集
*
* @param keys 可以 是一个string 也可以是一个string数组
* @return
*/
public Set<String> sinter(String... keys) { return jedis.sinter(keys);
} /**
* 通过key获取指定set中的交集 并将结果存入新的set中
*
* @param dstkey
* @param keys 可以 是一个string 也可以是一个string数组
* @return
*/
public Long sinterstore(String dstkey, String... keys) { return jedis.sinterstore(dstkey, keys);
} /**
* 通过key返回所有set的并集
*
* @param keys 可以 是一个string 也可以是一个string数组
* @return
*/
public Set<String> sunion(String... keys) { return jedis.sunion(keys);
} /**
* 通过key返回所有set的并集,并存入到新的set中
*
* @param dstkey
* @param keys 可以 是一个string 也可以是一个string数组
* @return
*/
public Long sunionstore(String dstkey, String... keys) { return jedis.sunionstore(dstkey, keys);
} /**
* 通过key将set中的value移除并添加到第二个set中
*
* @param srckey 需要移除的
* @param dstkey 添加的
* @param member set中的value
* @return
*/
public Long smove(String srckey, String dstkey, String member) { return jedis.smove(srckey, dstkey, member);
} /**
* 通过key获取set中value的个数
*
* @param key
* @return
*/
public Long scard(String key) { return jedis.scard(key);
} /**
* 通过key判断value是否是set中的元素
*
* @param key
* @param member
* @return
*/
public Boolean sismember(String key, String member) { return jedis.sismember(key, member);
} /**
* 通过key获取set中随机的value,不删除元素
*
* @param key
* @return
*/
public String srandmember(String key) { return jedis.srandmember(key);
} /**
* 通过key获取set中所有的value
*
* @param key
* @return
*/
public Set<String> smembers(String key) { return jedis.smembers(key);
} /**
* 通过key向zset中添加value,score,其中score就是用来排序的
* 如果该value已经存在则根据score更新元素
*
* @param key
* @param score
* @param member
* @return
*/
public Long zadd(String key, double score, String member) { return jedis.zadd(key, score, member);
} /**
* 通过key删除在zset中指定的value
*
* @param key
* @param members 可以 是一个string 也可以是一个string数组
* @return
*/
public Long zrem(String key, String... members) { return jedis.zrem(key, members);
} /**
* 通过key增加该zset中value的score的值
*
* @param key
* @param score
* @param member
* @return
*/
public Double zincrby(String key, double score, String member) { return jedis.zincrby(key, score, member);
} /**
* 通过key返回zset中value的排名
* 下标从小到大排序
*
* @param key
* @param member
* @return
*/
public Long zrank(String key, String member) { return jedis.zrank(key, member);
} /**
* 通过key返回zset中value的排名
* 下标从大到小排序
*
* @param key
* @param member
* @return
*/
public Long zrevrank(String key, String member) { return jedis.zrevrank(key, member);
} /**
* 通过key将获取score从start到end中zset的value
* socre从大到小排序
* 当start为0 end为-1时返回全部
*
* @param key
* @param start
* @param end
* @return
*/
public Set<String> zrevrange(String key, long start, long end) { return jedis.zrevrange(key, start, end);
} /**
* 通过key返回指定score内zset中的value
*
* @param key
* @param max
* @param min
* @return
*/
public Set<String> zrangebyscore(String key, String max, String min) { return jedis.zrevrangeByScore(key, max, min);
} /**
* 通过key返回指定score内zset中的value
*
* @param key
* @param max
* @param min
* @return
*/
public Set<String> zrangeByScore(String key, double max, double min) { return jedis.zrevrangeByScore(key, max, min);
} /**
* 返回指定区间内zset中value的数量
*
* @param key
* @param min
* @param max
* @return
*/
public Long zcount(String key, String min, String max) { return jedis.zcount(key, min, max);
} /**
* 通过key返回zset中的value个数
*
* @param key
* @return
*/
public Long zcard(String key) { return jedis.zcard(key);
} /**
* 通过key获取zset中value的score值
*
* @param key
* @param member
* @return
*/
public Double zscore(String key, String member) { return jedis.zscore(key, member);
} /**
* 通过key删除给定区间内的元素
*
* @param key
* @param start
* @param end
* @return
*/
public Long zremrangeByRank(String key, long start, long end) { return jedis.zremrangeByRank(key, start, end);
} /**
* 通过key删除指定score内的元素
*
* @param key
* @param start
* @param end
* @return
*/
public Long zremrangeByScore(String key, double start, double end) { return jedis.zremrangeByScore(key, start, end);
} /**
* 返回满足pattern表达式的所有key
* keys(*)
* 返回所有的key
*
* @param pattern
* @return
*/
public Set<String> keys(String pattern) { return jedis.keys(pattern);
} /**
* 通过key判断值得类型
*
* @param key
* @return
*/
public String type(String key) { return jedis.type(key);
} /**
* 返回一个CGlib增强的工具类对象
* @return
*/
public static JedisUtil getJedisUtil() {
RedisInterceptor redisInterceptor = new RedisInterceptor();
JedisUtil jedisUtil = (JedisUtil) redisInterceptor.getInstance(new JedisUtil());
return jedisUtil;
} }
Jedis工具类的动态代理类
package com; import java.lang.reflect.Method; import org.apache.logging.log4j.Logger;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; /**
* Jedis工具类的动态代理
* 自动获取连接及归还连接
* @author zaizouGGG
*
*/
public class RedisInterceptor implements MethodInterceptor { private Logger logger = LogUtil.get(RedisInterceptor.class);
private JedisUtil targetObject;
// 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理
public Object getInstance(JedisUtil target) {
// 设置需要创建子类的类
this.targetObject = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
} @Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
targetObject.setJedis(RedisPool.getJedis());
logger.info("获取连接后连接池状态"+RedisPool.getNumActive() + "-" + RedisPool.getNumIdle() + "-" + RedisPool.getNumWaiters());
Object result = proxy.invoke(targetObject, args);
RedisPool.returnJedis(targetObject.getJedis());
logger.info("归还连接后连接池状态"+RedisPool.getNumActive() + "-" + RedisPool.getNumIdle() + "-" + RedisPool.getNumWaiters());
return result;
} }
操作代码
public static void main(String[] args){
//实例化一个增强的工具类
JedisUtil jedisUtil = JedisUtil.getJedisUtil();
//进行相关操作即可
value = jedisUtil.get(key);
}
动态代理模式_应用(Redis工具类)的更多相关文章
- 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_40、Redis工具类封装讲解和实战
笔记 4.Redis工具类封装讲解和实战 简介:高效开发方式 Redis工具类封装讲解和实战 1.常用客户端 https://redisdesktop.com/download ...
- Java设计模式系列之动态代理模式(转载)
代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...
- JAVA动态代理模式(从现实生活角度理解代码原理)
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...
- Java-马士兵动态代理模式
Java-马士兵动态代理模式 模拟jdk的动态代理的实现原理, 这些东西没有必要写出来,写项目的时候一般用不上,主要是为了面试和理解原理: java动态代理有什么作用 作用非常大,在很多底层框架中都会 ...
- 基于jdk proxy的动态代理模式
代理模式 是spring AOP机制的实现基础,有必要学习一下. 有两种,一种是目标类有接口的, 采用JDK动态代理,一种是目标类没接口的,采用CGLIB动态代理. 先看一组代码, package c ...
- Java静态代理与动态代理模式的实现
前言: 在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总找不到时间去找他,他也没办法.后来,房东想了一个办法,他找到 ...
- java jdk动态代理模式举例浅析
代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...
- 设计模式之jdk动态代理模式、责任链模式-java实现
设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...
- iOS的动态代理模式的实现
动态代理模式的应用很多,特别是在不能修改被代理类的前提下,要对执行某些方法时需要打log或者捕捉异常等处理时,是一个非常方便的方法.只需要少量修改客户端(场景类)代码和添加一个代理类就可以实现,这个符 ...
随机推荐
- C#学习笔记04--排序/查找/二维数组/交叉数组
一. 冒泡排序(重点) 思路: 每次比较把较小的放在前面, 大的放到后面; 图解:下图是最坏情况下的排序 ` 冒泡排序m个元素, 就有(m-1)趟排序, 第一趟m-1次, 第二趟 m-2次.... ...
- Spring Data Jpa的四种查询方式
一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...
- Django中间件部分源码分析
中间件源码分析 中间件简介 中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定的 ...
- 【BZOJ4001】【Luogu P3978】 [TJOI2015]概率论
题目描述: Description: Input 输入一个正整数N,代表有根树的结点数 Output 输出这棵树期望的叶子节点数.要求误差小于1e-9 Sample Input 1 Sample Ou ...
- session与cookie的介绍和两者的区别之其相互的关系
转:https://blog.csdn.net/weixin_37196194/article/details/55806366 本文分别对Cookie与Session做一个介绍和总结,并分别对两个知 ...
- 带着canvas去流浪系列之七 绘制水球图
[摘要] 用原生canvasAPI实现百度echarts 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI绘制 ...
- jQuery中detach&&remove&&empty三种方法的区别
jQuery中empty&&remove&&detach三种方法的区别 empty():移除指定元素内部的所有内容,但不包括它本身 remove():移除指定元素内部的 ...
- ceph分布式存储
存储分类: DAS:直连存储 ide线 sata线 usd线 sas线 NAS:网络附加存储 nfs samba ftp SAN:存储区域网络 issci SDS ...
- 关于简单的Excel多页签底层导出_电子底账导出为例(.net core)
[HttpPost] public ActionResult ExpEleAcc(string linknos) { string filenname = null; CommonResult< ...
- shell du sh 文件大小输出
按照文件大小升序输出结果: du -sh * | sort -h 如果要逆序输出,则: du -sh * | sort -hr