本次使用动态代理的初衷是学习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工具类)的更多相关文章

  1. 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_40、Redis工具类封装讲解和实战

    笔记 4.Redis工具类封装讲解和实战     简介:高效开发方式 Redis工具类封装讲解和实战         1.常用客户端 https://redisdesktop.com/download ...

  2. Java设计模式系列之动态代理模式(转载)

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...

  3. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  4. Java-马士兵动态代理模式

    Java-马士兵动态代理模式 模拟jdk的动态代理的实现原理, 这些东西没有必要写出来,写项目的时候一般用不上,主要是为了面试和理解原理: java动态代理有什么作用 作用非常大,在很多底层框架中都会 ...

  5. 基于jdk proxy的动态代理模式

    代理模式 是spring AOP机制的实现基础,有必要学习一下. 有两种,一种是目标类有接口的, 采用JDK动态代理,一种是目标类没接口的,采用CGLIB动态代理. 先看一组代码, package c ...

  6. Java静态代理与动态代理模式的实现

    前言:    在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总找不到时间去找他,他也没办法.后来,房东想了一个办法,他找到 ...

  7. java jdk动态代理模式举例浅析

    代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...

  8. 设计模式之jdk动态代理模式、责任链模式-java实现

    设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...

  9. iOS的动态代理模式的实现

    动态代理模式的应用很多,特别是在不能修改被代理类的前提下,要对执行某些方法时需要打log或者捕捉异常等处理时,是一个非常方便的方法.只需要少量修改客户端(场景类)代码和添加一个代理类就可以实现,这个符 ...

随机推荐

  1. 使用Query Store监控性能

    Query Store是SQL Server 2016中引入的语句性能监控和调优工具,它不仅自动捕获查询.执行计划和运行时统计信息的历史记录,而且还可以识别出由于执行计划更改而导致的性能差异,简化了性 ...

  2. day 19 os模块的补充 序列化 json pickle

    os   模块 os.path.abspath  规范绝对路径 os.path.split() 把路径分成两段,第二段是一个文件或者是文件夹 os.path.dirname    取第一部分 os.p ...

  3. DVWA学习之SQL注入

    DVWA学习之SQL注入 环境工具 dvwa 1.9 phpstudy firefox burpsuite 实验步骤 一.设置安全级别为LOW 1. 登录DVWA,并将安全级别设置为LOW 2. 进入 ...

  4. 国内开源C# WPF控件库Panuon.UI.Silver推荐

    国内优秀的WPF开源控件库,Panuon.UI的优化版本.一个漂亮的.使用样式与附加属性的WPF UI控件库,值得向大家推荐使用与学习. 今天站长(Dotnet9,站长网址:https://dotne ...

  5. #在windows上使用ngix重定向目录访问远程服务器文件详细实例

    为了在开发环境保持于生产环境相同的访问远程服务器文件资源的目录配置,需要在开发环境(windows)在远程文件服务器使用nignx重定向文件目录,因为网上的资料大都是copy的,解释比较笼统,也没有具 ...

  6. Bootstrap 元素居中设置

    一.Bootstrap水平居中 1. 文本:class ="text-center" 2. 图片居中:class = "center-block" 3.其他元素 ...

  7. Django ORM-objects-QuerySet

    Django ORM ORM执行查看原生SQL的两种方法 1.在setting中配置 LOGGING = { 'version': 1, 'disable_existing_loggers': Fal ...

  8. tabBarItem是模型,只有控件才有textColor属性

    如果通过模型设置控件的文字颜色,只能通过文本属性(富文本:颜色,字体,图文混排,空心)

  9. 2019-2020-1 20199304《Linux内核原理与分析》第七周作业

    进程的描述和进程的创建 1.进程描述 1.1操作系统的三大管理功能以及对应的抽象概念: 进程管理 内存管理 文件系统 1.2Linux进程的状态: (1)Linux中进程的状态细分可以分为七种: R运 ...

  10. 关于<form> autocomplete 属性

    基本知识 值 描述 on 默认.规定启用自动完成功能. off 规定禁用自动完成功能. autocomplete 属性规定表单是否应该启用自动完成功能. 自动完成允许浏览器预测对字段的输入.当用户在字 ...