在开发过程中,我们常会用到一些资源池,比如线程池、数据库连接池。在操作这些资源池之后,往往要将一开始得到的资源池对象释放回资源池。
在代码中通常这样实现
try { //从资源池获取一个资源,进行业务处理 } catch (Exception e) { //异常处理 }finally { //释放资源到资源池 }
每次进行业务逻辑处理的时候都这样写是不是很麻烦?使用AOP可以简化代码。
我们以JedisPool为例演示代码。JedisPool是一个典型的资源池,初始化一次,以后每次从里面得到jedis对象,用完后释放回JedisPool里面。
AOP相关知识请参考http://ye-liang.iteye.com/blog/2010797
JedisPool相关知识请参考http://ye-liang.iteye.com/blog/1998177
另外还用到了ThreadLocal类,相关知识请参考http://ye-liang.iteye.com/blog/2009763
操作JedisPool的工具类JedisPoolUtil,里面有初始化、获取一个jedis对象、释放资源等方法。
public class JedisPoolUtil { private static JedisPool pool = null; private static final int maxAcive = 3000; private static final int maxIdle = 2000; private static final long maxWait = 100000L; private static final boolean testOnBorrow = false; private static final boolean testWhileIdle = true; private static final int minEvictableIdleTime = 60000; private static final int timeBetweenEvictionRuns = 30000; private static final int numTestsPerEvictionRun = -1; private static final String redisIp = SystemCodes.redisIP; private static final int port = SystemCodes.redisPort; static { initialPool(); } private static void initialPool() { try { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxActive(maxAcive); config.setMaxIdle(maxIdle); config.setMaxWait(maxWait); config.setTestOnBorrow(testOnBorrow); config.setTestWhileIdle(testWhileIdle); config.setMinEvictableIdleTimeMillis(minEvictableIdleTime); config.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRuns); config.setNumTestsPerEvictionRun(numTestsPerEvictionRun); pool = new JedisPool(config, redisIp, port); } catch (Exception e) { e.printStackTrace(); } } public static Jedis getJedis() { Jedis jedis = pool.getResource(); return jedis; } public static void releaseJedis(Jedis jedis) { if (null != jedis) { try { pool.returnResource(jedis); } catch (Exception e) { e.printStackTrace(); } } } public static void returnBrokenResource(Jedis jedis) { if (null != jedis) { try { pool.returnBrokenResource(jedis); } catch (Exception e) { e.printStackTrace(); } } } public static Jedis getSingleJedis(){ Jedis jedisSingle = new Jedis(redisIp, port); return jedisSingle; } public static void releaseSingleJedis(Jedis jedis){ if(null != jedis){ try { jedis.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } }
JedisManager类。进一步封装了JedisPoolUtil的方法,用在本文一开始的try catch finally代码里面。因为在切面和dao里面都要用到jedis对象,为了简化代码,把jedis对象存在该类的ThreadLocal里面。
public class JedisManager { private static ThreadLocal<Jedis> localJedis = new ThreadLocal<Jedis>(); public static void begin() { if (localJedis.get() == null || (Jedis) localJedis.get() == null) { Jedis jedis = JedisPoolUtil.getJedis(); localJedis.set(jedis); } } public static Jedis getJedis(){ return (Jedis)localJedis.get(); } public static void returnBrokenResource(){ Jedis jedis = (Jedis)localJedis.get(); JedisPoolUtil.returnBrokenResource(jedis); } public static void releaseJedis(){ Jedis jedis = (Jedis)localJedis.get(); JedisPoolUtil.releaseJedis(jedis); localJedis.remove(); } }
切面类JedisAspect。这里我们用@Aspect方式实现AOP,所以spring配置文件需要引入<aop:aspectj-autoproxy proxy-target-class="true" />。
@Aspect public class JedisAspect { // 定义切入点 @Pointcut(value = "execution(* com.springaop.TestService.test(..))") public void jedisPointcut() { } // 环绕 @Around(value = "jedisPointcut()") public void arondAdvice(ProceedingJoinPoint jp) throws Throwable { System.out.println("===========around advice"); try { JedisManager.begin(); jp.proceed(); } catch (Throwable e) { JedisManager.returnBrokenResource(); throw e; }finally { JedisManager.releaseJedis(); } } }
切入点定义到service层。这里采用环绕通知的方式。jp.proceed()相当于调用目标对象。整个过程用try catch finally 包起来。一开始JedisManager.begin()获取jedis对象存到该线程的ThreadLocal里面。遇到异常释放jedis对象,最后将jedis对象返回资源池。
在dao里面要获取jedis对象就调用
Jedis jedis = JedisManager.getJedis();
这样service和dao层完全没有了一大推的try catch finally 。都交给了切面里面的通知方法去完成,只用写一次。
相关推荐
spring aop做的日志管理,网上看的,没测试过。
spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop
spring aop jar 包
spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...
描述一下Spring AOP? 在Spring AOP中关注点(concern)和横切关注点(cross-cutting concern)有什么不同? AOP有哪些可用的实现? Spring中有哪些不同的通知类型(advice types)? Spring AOP 代理是什么? 引介...
一、适合人群 1、具备一定Java编程基础,初级开发者 2、对springboot,mybatis,mysql有基本认识 3、对spring aop认识模糊的,不清楚如何实现Java 自定义注解的 ...4、spring boot,mybatis,druid,spring aop的使用
Spring AOP 日志管理 实例LoggingThrowsAdvice.java
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
spring aop的demo spring aop的demo
springaop依赖的jar包,spring版本2.5.6,如果需要,可以下载使用,欢迎各位评论指出不足
Spring框架的关键组件之一是面向方面编程(AOP)框架。 面向方面的编程需要将程序逻辑分解成不同的部分。 此教程将通过简单实用的方法来学习Spring框架提供的AOP/面向方面编程。
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供...
死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序
Spring aop Spring aop
Spring AOP 几个不同使用方法的完整例子,使用Junit4c测试, 在我的博客上有不同配置组合的说明,可以参考
springAOP详解
spring aop
开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE...
AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析...
Spring AOP简单demo 入门级的 advice