动态代理模式_应用(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或者捕捉异常等处理时,是一个非常方便的方法.只需要少量修改客户端(场景类)代码和添加一个代理类就可以实现,这个符 ...
随机推荐
- 封装Ajax和跨域
目录 引言 封装ajax 案例:使用自封装ajax 案例:动态加载瀑布流 跨域 引言 对于Ajax现在相信大家已经不会陌生了,无论是原生的XMLHttpRequest方式发送还是通过jQuery框架中 ...
- tar文件归档
tar是UNIX和类UNIX系统上的压缩,备份工具, 名字来源于Tape archive--磁盘归档,最初的时候是用来将数据储存,备份到磁带上的.而今最简单的备份方法是添加新的磁盘或者在云端存储,但即 ...
- linux网络配置(iproute2)
iproute2家族 ip命令:show / manipulate routing,devices,policy routing and tunnels(显示/操纵路由.设备.策略路由和隧道) 语法 ...
- jquery怎么添加多个类名
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- day02_Requests模块
1.anaconda的安装 1.1 .安装可执行程序 1.2 .配置环境变量 根据环境变量的先后顺序去查找可执行程序文件,如果查找到就执行,如果查找不到就报错. anaconda主要配置: ...
- Dubbo实现登陆
一.目录展示 二.dubbo_logins_service 2.1 实体类和service层 2.2 logins实体类 package com.login.entity; import java.i ...
- React Native从零开始构建项目(2019)
环境搭建,参考官网 https://reactnative.cn/ 安装 Xcode Android Studio 目的,实现本地热重载开发,使用vsCode 运行失败,重新执行react-nativ ...
- CCNA 之 十 ACL 访问控制列表
ACL 访问控制列表 ACL(Access Control List) 接入控制列表 ACL 的量大主要功能: 流量控制 匹配感兴趣流量 标准访问控制列表 只能根据源地址做过滤 针对曾哥协议采取相关动 ...
- php 图片指定留白叠加缩放
遇到这样一个需求:原图大小不一,而且留白也大小不一,需要将原图切出来一个核心图,然后将图片左右留白,组成一个其他尺寸的图片.换句话说,原图在新图片中的位置是可以控制的. 这里思路是:先创建一个规定大小 ...
- Thinkphp5——实现分页(模型和Db分页,多种方法)
现在很多网站的数据量的很多,如果全部在一页里显示效果不好,数据量太大,那怎么办?这时我们就需要分页,而分页的好处就是分段显示数据,这样页面就不用加载很多数据,需要时才加载,下面我教大家实现ThinkP ...