spring拦截方法的配置和实现

最近项目要求,对于某个某些方法执行异步任务,就是说,对于那些接口(调用时间长,没必要立刻得到接口执行结果的接口)执行异步调用,这样主线程就会执行的时间就很短了,我的实现呢是用spring环绕通知拦截所有的方法(这些方法先用spring aop进行切片)、

配置如下:

 
   
相应的拦截器的代码为:

package com.paic.icore.aops.common.biz.util;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;

import com.paic.icore.aops.common.jedis.message.MsgRedisPoolUtils;

public class MethodInterceptor {

	@Autowired
	private AopsLogger logger;

	@Autowired
	private MsgRedisPoolUtils msgRedis;
	
	public Object logger(ProceedingJoinPoint pjp) throws Throwable {
		Object obj = null;
		MethodSignature joinPointObject = (MethodSignature) pjp.getSignature();  
        Method method = joinPointObject.getMethod();    
		boolean flag = method.isAnnotationPresent(AsynchTask.class) ;    
        if(flag){
        	//这里要判断是否是异步线程调用,还是程序调用
        	String flagValue = method.getName()+JSONArray.fromObject(pjp.getArgs()).toString();
        	String isDo = msgRedis.get(flagValue);
        	if(null==isDo || "".equals(isDo))//表示是程序调用
        	{
        		// 获取目标对象类名
        		String clazzName = pjp.getTarget().getClass().getName();
        		// 获取方法名
				String methodName = pjp.getSignature().getName();
				logger.trace("================拦截到" + clazzName + "的" + methodName + "方法");
        		// 获取执行方法的参数
        		Object[] args = pjp.getArgs();
            	StringBuffer params =new StringBuffer();//参数的数组
            	Object[] paramsType = method.getParameterTypes();
            	for(int i=0;i map =new HashMap();
            	AsynchTask methodInterceptor = method.getAnnotation(AsynchTask.class); 
                String interfaceName = methodInterceptor.value();
            	map.put("className", clazzName);
            	map.put("methodName", methodName);
            	map.put("params", params.toString());
            	map.put("interfaceName", interfaceName);//这里把那个方法所在的接口别名拿到
            	msgRedis.saveHashMapToJedis(String.valueOf(taskId), map, -1);
            	obj = true;
        	}
        	else if(null!=isDo)//表示是异步任务调用
        	{
        		obj = pjp.proceed();//放方法过去
        	}
        }
        else//没有加那个拦截方法的注解的
        {
        	obj = pjp.proceed();//放方法过去
        }
		return obj;
	}
}

把执行的方法放进缓存系统后,再合适的时机反射调用即可(这里用得是spring的task任务机制,1秒一次滴)


package com.paic.icore.aops.task.apptask.action;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

import net.sf.json.JSONArray;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import com.paic.icore.aops.common.biz.util.AopsLogger;
import com.paic.icore.aops.common.biz.util.DateUtil;
import com.paic.icore.aops.common.jedis.message.MsgRedisPoolUtils;
import com.paic.icore.aops.points.service.IncomePointService;
import com.paic.pafa.app.lwc.core.context.support.PafaApplicationContext;
import com.paic.pafa.biz.AppContext;
import com.paic.pafa.web.BaseRest;
//测试异步调用程序
@Component
public class AsynchTaskAction extends BaseRest {
	
	@Autowired
	private AopsLogger logger;
	
	//注入线程池
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;
	
	@Autowired
	private MsgRedisPoolUtils msgRedis;
	
	@Autowired
	private IncomePointService incomePointService;
	
	
	@Scheduled(cron = "0/1 * * * * ?")
	public void doAsynchTask(){
		int count =taskExecutor.getActiveCount();
 		int maxpollsize = taskExecutor.getMaxPoolSize();
		count =taskExecutor.getActiveCount();
		logger.tasklog("调用接口:doTest:当前活动线程数:count="+count);
		logger.tasklog("线程池允许的最大线程数:maxpollsize="+maxpollsize);
		if(count doTest");
		}
	}
	
	//通过接口方法名,拿到实现类的方法
	private Method getImplMehodByInterMehtod(Object obj,Method interfaceMethod ) throws SecurityException, NoSuchMethodException{
			return obj.getClass().getMethod(interfaceMethod.getName(), interfaceMethod.getParameterTypes());
	}
	
}

其中方法上用到了一个注解,就是自定义注解

注解定义如下:

package com.paic.icore.aops.common.biz.util;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME)
public @interface AsynchTask {
	//接口的实现类的别名
	String value();
}

这个注解必须加在service所对应的接口方发上,就是说,拦截那个方法把这个注解加上即可


经测试功能ok

你可能感兴趣的:(spring,spring,缓存系统,redis,反射,拦截方法)