动态代理
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务,动态代理:在程序运行时,运用反射机制创建
简单的动态代理例子
父类接口
package myproxy;
public interface SubClass {
public void hello();
}
子类package myproxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args){
SubClass subClass = new RealSubClass();
ProxyHander h = new ProxyHander(subClass);
SubClass proxy = (SubClass) Proxy.newProxyInstance(subClass.getClass().getClassLoader(), subClass.getClass().getInterfaces(), h);
//System.out.println(proxy);
proxy.hello();
}
}
代理类package myproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHander implements InvocationHandler {
private Object pObject;
public ProxyHander(Object pObject){
this.pObject = pObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before");
System.out.println("Method" + method.getName());
method.invoke(pObject, args);
System.out.println("after");
return null;
}
}
客户端
DefaultAdvisorAutoProxyCreator
MyRegexpMethodPointcutAdvisor
ClassUtils
ProfilerInterceptor
最后不要忘记在Spring的配置文件中 事物控制配置中添加咱们的切入点
一个线程一个唯一的UUID 根据UUID即可知道方法的轨迹信息
package myproxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args){
SubClass subClass = new RealSubClass();
ProxyHander h = new ProxyHander(subClass);
SubClass proxy = (SubClass) Proxy.newProxyInstance(subClass.getClass().getClassLoader(), subClass.getClass().getInterfaces(), h);
//System.out.println(proxy);
proxy.hello();
}
}
利用Spirng动态代理完成方法监控
请看applicationContext.xml配置文件
<bean id="servcieAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- <property name="interceptorNames" value="txInterceptor" /> -->
<property name="interceptorNames">
<list>
<value>txInterceptor</value>
</list>
</property>
<property name="beanNames" value="*Service" />
</bean>
这个是spring事物控制中的代理,这里只代理Service类所以为了监控所有方法还要代理Action DAO 等等所有类的方法,只有一个service类是不够的
所以配置applicationContext.xml文件
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="true" />
</bean>
<bean id="interceptorAdvisor" class="net.uni.ap.aop.MyRegexpMethodPointcutAdvisor">
业务实现方法名匹配
<property name="patterns">
<list>
<value>com.*</value>
</list>
</property>
<property name="advice">
<ref bean="interceptorAdvice" />
</property>
</bean>
<bean id="interceptorAdvice" class="net.uni.ap.aop.ProfilerInterceptor">
</bean>
DefaultAdvisorAutoProxyCreator
一个更加通用而且强大得多的自动代理创建器是DefaultAdvisorAutoProxyCreator。它自动应用当前上下文中适当的advisor,无需在自动代理advisor的bean定义中包括bean的名字。 比起BeanNameAutoProxyCreator,它提供了同样关于一致性配置的优点而避免了前者的重复性。
使用这个功能将涉及:
说明一个 DefaultAdvisorAutoProxyCreator的bean定义在同一个或者相关的上下文中说明任意数量的advisor。注意这些必须是advisor而不仅仅是拦截器或者其它通知。这点是必要的因为必须有一个切入点被评估,以便检查每个通知候选bean定义的合适性。
DefaultAdvisorAutoProxyCreator将自动评估包括在每个advisor中的切入点,来看看它应当应用哪个(如果有的话)通知到每个业务对象
这意味着可以向每个业务对象应用任意数量的advisor。对于一个业务对象,如果没有任何advisor中的切入点匹配它的任何方法,这个对象将不会被代理。当为新的业务对象加入bean定义时,如果有必要它们将自动被代理。
通常自动代理的好处是它让调用者或者被依赖对象不能得到一个没有通知过的对象。在这个ApplicationContext上调用getBean("businessObject1")将返回一个AOP代理,而不是目标业务对象。
使用这个功能将涉及:
说明一个 DefaultAdvisorAutoProxyCreator的bean定义在同一个或者相关的上下文中说明任意数量的advisor。注意这些必须是advisor而不仅仅是拦截器或者其它通知。这点是必要的因为必须有一个切入点被评估,以便检查每个通知候选bean定义的合适性。
DefaultAdvisorAutoProxyCreator将自动评估包括在每个advisor中的切入点,来看看它应当应用哪个(如果有的话)通知到每个业务对象
这意味着可以向每个业务对象应用任意数量的advisor。对于一个业务对象,如果没有任何advisor中的切入点匹配它的任何方法,这个对象将不会被代理。当为新的业务对象加入bean定义时,如果有必要它们将自动被代理。
通常自动代理的好处是它让调用者或者被依赖对象不能得到一个没有通知过的对象。在这个ApplicationContext上调用getBean("businessObject1")将返回一个AOP代理,而不是目标业务对象。
MyRegexpMethodPointcutAdvisor
继承RegexpMethodPointcutAdvisor,并重写父类里的方法。其目的为可以遍历指定包下的所有类文件,如果不重写只能指定某一包下的方法或者根据正则表达式匹配一定规则的方法
其代码为
package net.uni.ap.aop;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractRegexpMethodPointcut;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
import org.springframework.util.ObjectUtils;
public class MyRegexpMethodPointcutAdvisor extends RegexpMethodPointcutAdvisor{
private String[] patterns;
private AbstractRegexpMethodPointcut pointcut;
private final Object pointcutMonitor = new SerializableMonitor();
/**
* Create an empty RegexpMethodPointcutAdvisor.
* @see #setPattern
* @see #setPatterns
* @see #setAdvice
*/
public MyRegexpMethodPointcutAdvisor() {
}
/**
* Create a RegexpMethodPointcutAdvisor for the given advice.
* The pattern still needs to be specified afterwards.
* @param advice the advice to use
* @see #setPattern
* @see #setPatterns
*/
public MyRegexpMethodPointcutAdvisor(Advice advice) {
setAdvice(advice);
}
/**
* Create a RegexpMethodPointcutAdvisor for the given advice.
* @param pattern the pattern to use
* @param advice the advice to use
*/
public MyRegexpMethodPointcutAdvisor(String pattern, Advice advice) {
setPattern(pattern);
setAdvice(advice);
}
/**
* Create a RegexpMethodPointcutAdvisor for the given advice.
* @param patterns the patterns to use
* @param advice the advice to use
*/
public MyRegexpMethodPointcutAdvisor(String[] patterns, Advice advice) {
setPatterns(patterns);
setAdvice(advice);
}
/**
* Set the regular expression defining methods to match.
* <p>Use either this method or {@link #setPatterns}, not both.
* @see #setPatterns
*/
public void setPattern(String pattern) {
setPatterns(new String[] {pattern});
}
/**
* Set the regular expressions defining methods to match.
* To be passed through to the pointcut implementation.
* <p>Matching will be the union of all these; if any of the
* patterns matches, the pointcut matches.
* @see AbstractRegexpMethodPointcut#setPatterns
*/
public void setPatterns(String[] patterns) {
String packageName = "com.fesco.mis.business";
String[] classNames = ClassUtils.getListClass(packageName);
for (String string : classNames) {
System.out.println(string);
}
this.patterns = classNames;
}
/**
* Initialize the singleton Pointcut held within this Advisor.
*/
public Pointcut getPointcut() {
synchronized (this.pointcutMonitor) {
if (this.pointcut == null) {
this.pointcut = createPointcut();
this.pointcut.setPatterns(this.patterns);
}
return pointcut;
}
}
/**
* Create the actual pointcut: By default, a {@link JdkRegexpMethodPointcut}
* will be used.
* @return the Pointcut instance (never <code>null</code>)
*/
protected AbstractRegexpMethodPointcut createPointcut() {
return new JdkRegexpMethodPointcut();
}
@Override
public String toString() {
return getClass().getName() + ": advice [" + getAdvice() +
"], pointcut patterns " + ObjectUtils.nullSafeToString(this.patterns);
}
/**
* Empty class used for a serializable monitor object.
*/
private static class SerializableMonitor implements Serializable {
}
}
ClassUtils
查找指定包下的所有类和接口
代码
package net.uni.ap.aop;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ClassUtils {
public static void main(String[] args){
String packageName = "com.fesco.mis.business.cs";
String[] classNames = ClassUtils.getListClass(packageName);
System.err.println(classNames.length);
}
public static String[] getListClass(String packString) {
Set set = getClasses(packString);
List<String> list = new ArrayList<String>();
for (Object object : set) {
if(object.toString().split(" ")[0].equals("class")
&& !object.toString().split(" ")[1].contains("BO")){
list.add((object.toString().split(" ")[1]+".*"));
}
}
String[] strings = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
strings[i] = list.get(i);
}
return strings;
}
/**
* 从包package中获取所有的Class
*
* @param pack
* @return
*/
public static Set<Class<?>> getClasses(String pack) {
// 第一个class类的集合
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
// 是否循环迭代
boolean recursive = true;
// 获取包的名字 并进行替换
String packageName = pack;
String packageDirName = packageName.replace('.', '/');
// 定义一个枚举的集合 并进行循环来处理这个目录下的things
Enumeration<URL> dirs;
try {
dirs = Thread.currentThread().getContextClassLoader()
.getResources(packageDirName);
// 循环迭代下去
while (dirs.hasMoreElements()) {
// 获取下一个元素
URL url = dirs.nextElement();
// 得到协议的名称
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol)) {
System.err.println("file类型的扫描");
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件 并添加到集合中
findAndAddClassesInPackageByFile(packageName, filePath,
recursive, classes);
} else if ("jar".equals(protocol)) {
// 如果是jar包文件
// 定义一个JarFile
System.err.println("jar类型的扫描");
JarFile jar;
try {
// 获取jar
jar = ((JarURLConnection) url.openConnection())
.getJarFile();
// 从此jar包 得到一个枚举类
Enumeration<JarEntry> entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
// 获取后面的字符串
name = name.substring(1);
}
// 如果前半部分和定义的包名相同
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
// 如果以"/"结尾 是一个包
if (idx != -1) {
// 获取包名 把"/"替换成"."
packageName = name.substring(0, idx)
.replace('/', '.');
}
// 如果可以迭代下去 并且是一个包
if ((idx != -1) || recursive) {
// 如果是一个.class文件 而且不是目录
if (name.endsWith(".class")
&& !entry.isDirectory()) {
// 去掉后面的".class" 获取真正的类名
String className = name.substring(
packageName.length() + 1,
name.length() - 6);
try {
// 添加到classes
classes.add(Class
.forName(packageName + '.'
+ className));
} catch (ClassNotFoundException e) {
// log
// .error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}
}
} catch (IOException e) {
// log.error("在扫描用户定义视图时从jar包获取文件出错");
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
/**
* 以文件的形式来获取包下的所有Class
*
* @param packageName
* @param packagePath
* @param recursive
* @param classes
*/
public static void findAndAddClassesInPackageByFile(String packageName,
String packagePath, final boolean recursive, Set<Class<?>> classes) {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory()) {
// log.warn("用户定义包名 " + packageName + " 下没有任何文件");
return;
}
// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter() {
// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
public boolean accept(File file) {
return (recursive && file.isDirectory())
|| (file.getName().endsWith(".class"));
}
});
// 循环所有文件
for (File file : dirfiles) {
// 如果是目录 则继续扫描
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(
packageName + "." + file.getName(),
file.getAbsolutePath(), recursive, classes);
} else {
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0,
file.getName().length() - 6);
try {
// 添加到集合中去
// classes.add(Class.forName(packageName + '.' +
// className));
// 经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
classes.add(Thread.currentThread().getContextClassLoader()
.loadClass(packageName + '.' + className));
} catch (ClassNotFoundException e) {
// log.error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}
}
ProfilerInterceptor
切入点类,继承Spring MethodInterceptor 类
其代码为
package net.uni.ap.aop;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fesco.fws.utils.JsonUtils;
public class ProfilerInterceptor implements MethodInterceptor{
private transient final Logger logger = LoggerFactory.getLogger(ProfilerInterceptor.class);
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Thread current = Thread.currentThread();
if(null == AopContextHandler.getContextUUID()){
String uuid = UUID.randomUUID().toString();
AopContextHandler.setContextUUID(uuid);
}
//用 commons-lang 提供的 StopWatch 计时,Spring 也提供了一个 StopWatch
StopWatch clock = new StopWatch();
clock.start(); //计时开始
Object result = null;
//监控的类名
String className = invocation.getMethod().getDeclaringClass().getSimpleName();
//监控的方法名
String methodName = className + "." + invocation.getMethod().getName();
Object[] objs = invocation.getArguments();
try {
//这个是我们监控的bean的执行并返回结果
result = invocation.proceed();
} catch (Throwable e) {
//监控的参数
objs = invocation.getArguments();
logger.error("数据库执行异常,方法名:" + methodName + "参数:" + getString(objs), e);
throw e;
}
clock.stop(); //计时结束
if(!(methodName.contains("CacheMapService") || methodName.contains("ActionSupport")
|| methodName.contains("setSession") ||methodName.contains("setServletResponse")
|| methodName.contains("setServletRequest"))){
logger.error("执行的方法:"+methodName + "(" + getString(objs) +") 执行时间:" + clock.getTime() +" UUID:"+AopContextHandler.getContextUUID());
}
return result;
}
/**
* 这个类主要是用于输出方法的参数
*
* @param objs
* @return
*/
@SuppressWarnings("unchecked")
public String getString(Object[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "";
StringBuilder b = new StringBuilder();
for (int i = 0;; i++) {
if (a[i] instanceof Object[]) {
b.append(getString((Object[]) a[i]));
} else {
try {
if(null != a[i] && !(a[i].toString().contains("BO") || a[i].toString().contains("struts2") || a[i].toString().contains("ResponseFacade"))){
b.append(String.valueOf(JsonUtils.toJSONString(a[i])));
}else if( null != a[i]){
logger.error(a[i].toString());
}
} catch (Exception e) {
if(a[i] != null){
b.append(a[i].toString());
}else{
b.append("null");
}
}
}
if (i == iMax)
return b.toString();
b.append(", ");
}
}
}
遇到的问题
因为事物管理中已经代理了BO的Service类
所有再次开启代理时会出现问题,所有在遍历指定报下的类和接口时过滤掉已经被代理的BO类
因为相当是使用两次代理,使用的是同一个切入点,所以使用线程变量ThreadLocal来监控一个线程执行的过程
ThreadLocal类代码
package net.uni.ap.aop;
/**
*
* 处理内容:AOP 监控方法变量
* @version: 1.0
* @see:net.uni.ap.aop.AopContextHandler.java
* @date:2016-1-18
* @author:梅海波
*/
public class AopContextHandler {
/**
* 存放UUID
*/
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setContextUUID(String UUID){
contextHolder.set(UUID);
}
public static String getContextUUID(){
return contextHolder.get();
}
public static void removeContextUUID(){
contextHolder.remove();
}
}
上篇文章已经写过,ThreadLocal变量会随着线程的销毁而回收,所以不用关心内存泄露问题
监控结果为
016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("DATA_VALID_STATE") 执行时间:20 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("MSG_READ") 执行时间:66 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("DATA_VALID_STATE") 执行时间:81 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("MSG_ASSC_TYPE") 执行时间:33 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("MSG_ASSC_TYPE") 执行时间:60 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IUserBO.getObject(10011) 执行时间:105 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("MSG_SEND_TYPE") 执行时间:54 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("MSG_ASSC_TYPE") 执行时间:59 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IUserBO.getObject(10011) 执行时间:108 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("MSG_SEND_TYPE") 执行时间:10 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:49 - 执行的方法:IDictInfoBO.getStore("JBPM_APPLY_STATE") 执行时间:76 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:53 - 执行的方法:IBaseFileCommonModelInfoBO.queryCommonModel({"dataIds":null,"emptyMsg":true,"list":[{"createTime":1428927642000,"creatorId":758111,"desc":null,"entryType":null,"fileLength":13958,"fileState":null,"fromIp":"127.0.0.1","id":15792,"modelTitle":"眼神因子测试","modelType":"3","originalName":"1234.xlsx","path":"/Upload/41","saveName":"1234-1428927641443.xlsx"},{"createTime":1429078432000,"creatorId":758111,"desc":"批量修改延伸因子","entryType":null,"fileLength":14375,"fileState":null,"fromIp":"127.0.0.1","id":15811,"modelTitle":"延伸因子","modelType":"3","originalName":"批量修改延伸因子-1.0.1.14219V10.xlsx","path":"/Upload/41/批量修改延伸因子-1.0.1.14219V10-1429078432366.xlsx/41/批量修改延伸因子-1.0.1.14219V10-1430474645727.xlsx/41/批量修改延伸因子-1430659145163.xlsx/41","saveName":"批量修改延伸因子-1.0.1.14219V10-1430659375967.xlsx"},{"createTime":1415845668000,"creatorId":758111,"desc":"沙发111","entryType":null,"fileLength":2995,"fileState":null,"fromIp":"0:0:0:0:0:0:0:1","id":13799,"modelTitle":"测试12232","modelType":"4","originalName":"error.html","path":"/Upload/41/fontDemo-1415845624739.html/41","saveName":"error-1415846235224.html"},{"createTime":1429176198000,"creatorId":758111,"desc":null,"entryType":null,"fileLength":468,"fileState":null,"fromIp":"0:0:0:0:0:0:0:1","id":15825,"modelTitle":"yyy","modelType":"3","originalName":"博能科技笔试题.txt","path":"/Upload/41","saveName":"博能科技笔试题-1429176178949.txt"}],"pageno":1,"rowsize":10,"start":0,"total":1,"totalrows":4}, {"createTime":null,"creatorId":null,"desc":null,"entryType":null,"fileLength":null,"fileState":null,"fromIp":null,"id":null,"modelTitle":null,"modelType":null,"originalName":null,"path":null,"saveName":null}) 执行时间:2193 UUID:ac7a150a-0488-44a9-bb8a-708394c0a0f9
2016-01-18 18:38:53 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(1510, 1908, "/mis") 执行时间:1643 UUID:c6b14a94-6777-4fc1-bea7-edfc7c67b668
2016-01-18 18:38:53 - 执行的方法:IQuestionPublishBO.getQPList({"activeState":null,"answer":null,"bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":null,"formSerachDate":null,"id":null,"isEffect":null,"operTime":null,"repId":null,"repName":null,"roleId":null,"type":-1,"version":null}, {"dataIds":null,"emptyMsg":true,"list":[{"activeState":null,"answer":"<p>\r\n\t 是</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"阿斯","formSerachDate":null,"id":1096,"isEffect":null,"operTime":1403492965000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":"<p>\r\n\tas</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"as","formSerachDate":null,"id":1095,"isEffect":null,"operTime":1403490682000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":"<p>\r\n\t阿斯达阿斯达阿斯达</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"阿斯达","formSerachDate":null,"id":1092,"isEffect":null,"operTime":1403260339000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":"<p>\r\n\t阿斯达阿斯打算的</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"阿斯达","formSerachDate":null,"id":1091,"isEffect":null,"operTime":1403259593000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":"<p>\r\n\tss</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"ssss","formSerachDate":null,"id":1088,"isEffect":null,"operTime":1403232850000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":"<p>\r\n\tdsadadadadadada</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"asda","formSerachDate":null,"id":1087,"isEffect":null,"operTime":1403175743000,"repId":null,"repName":null,"roleId":3814164,"type":4,"version":null},{"activeState":null,"answer":"<p>\r\n\tas</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"asda","formSerachDate":null,"id":1086,"isEffect":null,"operTime":1403175057000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":null,"bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"asdad","formSerachDate":null,"id":1085,"isEffect":null,"operTime":1403175008000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":"<p>\r\n\tdasdadsads</p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"asdsa","formSerachDate":null,"id":1084,"isEffect":null,"operTime":1403174929000,"repId":null,"repName":null,"roleId":3814164,"type":1,"version":null},{"activeState":null,"answer":"<p>\r\n\t<img alt=\"\" src=\"http://ww3.sinaimg.cn/bmiddle/61e89b74tw1eh10a0ee8zj20id0fxdhb.jpg\" style=\"width: 115px; height: 100px; float: left;\" /></p>\r\n","bur":null,"creDate":null,"custCon":null,"depId":null,"depName":null,"descsth":"1","formSerachDate":null,"id":1062,"isEffect":null,"operTime":1401785587000,"repId":null,"repName":null,"roleId":3816955,"type":1,"version":null}],"pageno":1,"rowsize":10,"start":0,"total":3,"totalrows":30}) 执行时间:2201 UUID:70695da4-9caa-4ca5-9a27-5e86311d2c1e
2016-01-18 18:38:54 - 执行的方法:IBatchOperBO.findBatchOperList({"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":null,"batchType":null,"completeNum":null,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":null,"depId":null,"depName":null,"errorIds":null,"errorNum":null,"findMapKey":false,"formSerachDate":null,"id":null,"lastCompleteTime":null,"mapKey":null,"nowCount":true,"overNum":null,"overSecond":null,"refreshTime":null,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":null,"userId":10011,"version":null}, {"dataIds":null,"emptyMsg":true,"list":[{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"批量创建交互订单项","batchType":7,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":1,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":30050,"lastCompleteTime":null,"mapKey":"71452654200430","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1452654200000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"批量创建交互订单项","batchType":7,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":1,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":30034,"lastCompleteTime":null,"mapKey":"71452594537863","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1452594537000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"批量创建交互订单项","batchType":7,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":1,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29934,"lastCompleteTime":null,"mapKey":"71452499989750","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1452499989000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"批量创建交互订单项","batchType":7,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":1,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29933,"lastCompleteTime":null,"mapKey":"71452499973012","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1452499973000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"批量按人终止(换公司)","batchType":20,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":1,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29447,"lastCompleteTime":null,"mapKey":"201450692360583","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1450692360000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"按变化明细处理申报工资","batchType":11,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":3,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29179,"lastCompleteTime":null,"mapKey":"111449567128252","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1449567128000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"按变化明细处理申报工资","batchType":11,"completeNum":1,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":3,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29271,"lastCompleteTime":1449566737000,"mapKey":"111449566537609","nowCount":null,"overNum":2,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1449566537000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"按变化明细处理申报工资","batchType":11,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":3,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29439,"lastCompleteTime":null,"mapKey":"111449566208055","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1449566208000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"按变化明细处理申报工资","batchType":11,"completeNum":1,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":3,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29438,"lastCompleteTime":1449565956000,"mapKey":"111449565569680","nowCount":null,"overNum":2,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1449565569000,"userId":10011,"version":null},{"activeState":null,"allStep":null,"batchNum":null,"batchOtherLink":null,"batchRemark":null,"batchState":null,"batchStep":null,"batchStepState":null,"batchStepTitle":null,"batchSumStep":null,"batchTitle":"按变化明细处理申报工资","batchType":11,"completeNum":0,"completeTime":null,"creDate":null,"currUser":null,"custCon":null,"dataIds":null,"dataNum":3,"depId":null,"depName":null,"errorIds":null,"errorNum":0,"findMapKey":false,"formSerachDate":null,"id":29400,"lastCompleteTime":null,"mapKey":"111449564108756","nowCount":null,"overNum":null,"overSecond":null,"refreshTime":3,"relationOper":null,"relationalData":null,"repId":null,"repName":null,"startTime":1449564108000,"userId":10011,"version":null}],"pageno":1,"rowsize":10,"start":0,"total":15,"totalrows":141}) 执行时间:2548 UUID:61e2480a-2b35-46ae-bcd7-0bffc3b5ac98
2016-01-18 18:38:54 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(11012099, 1908, "/mis") 执行时间:1653 UUID:a546b4e9-c440-44d2-85e8-d9c433c5095b
2016-01-18 18:38:54 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(1453, 1908, "/mis") 执行时间:1731 UUID:43b04354-0a2f-4e89-8e41-cf271ec89c41
2016-01-18 18:38:54 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(2182, 1908, "/mis") 执行时间:2142 UUID:3068d35e-f304-4011-8c3c-7a0dead2151d
2016-01-18 18:38:54 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(2218, 1908, "/mis") 执行时间:2272 UUID:7c78d2d5-7fcf-43b7-b200-941a3adfd658
2016-01-18 18:38:54 - 执行的方法:IJbpmBO.findMyTaskListSize("10011") 执行时间:819 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:54 - 执行的方法:IDictInfoBO.getStore("QUESTION_TYPE") 执行时间:651 UUID:70695da4-9caa-4ca5-9a27-5e86311d2c1e
2016-01-18 18:38:54 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(11018064, 1908, "/mis") 执行时间:2061 UUID:3556b1d7-c1e6-48f9-8c83-ddb803afd6d9
2016-01-18 18:38:54 - 执行的方法:IDictInfoBO.getStore("QUESTION_TYPE") 执行时间:812 UUID:ac7a150a-0488-44a9-bb8a-708394c0a0f9
2016-01-18 18:38:54 - 执行的方法:IBaseSubScriptionModBO.findUserModPage({"dataIds":null,"emptyMsg":true,"list":[],"pageno":1,"rowsize":7,"start":0,"total":0,"totalrows":0}, net.uni.in1.model.User@6a056bd9) 执行时间:63 UUID:a28e38b4-019d-4af0-9b8c-f6301bbd898e
2016-01-18 18:38:54 - 执行的方法:IFunctionBO.getFunTreeByUserRole("1908", true, "/mis") 执行时间:103 UUID:7ca61b57-df7d-496b-9739-ae9849113508
2016-01-18 18:38:55 - 执行的方法:IDictInfoBO.getStore("QUESTION_TYPE") 执行时间:180 UUID:70695da4-9caa-4ca5-9a27-5e86311d2c1e
2016-01-18 18:38:55 - 执行的方法:IBaseMessageReceiveBO.getUnReadMsgCount(1, net.uni.in1.model.User@6a056bd9) 执行时间:182 UUID:ad28c722-b710-4370-847c-3bd238b5b11b
2016-01-18 18:38:55 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(2200565, 1908, "/mis") 执行时间:106 UUID:73e3ece9-9be3-4ecc-8c79-6c24322d874d
2016-01-18 18:38:55 - 执行的方法:IBaseTaskAgentBO.getUserTaskAgent({"dataIds":null,"emptyMsg":true,"list":[],"pageno":1,"rowsize":7,"start":0,"total":0,"totalrows":0}, {"actualEndTime":null,"benTime":null,"endTime":null,"id":null,"operTime":null,"operator":null,"state":null,"user":null,"userId":10011,"userRole":null,"userRoleId":null}) 执行时间:179 UUID:43b04354-0a2f-4e89-8e41-cf271ec89c41
2016-01-18 18:38:55 - 执行的方法:IFunctionBO.getAllFunctionsByUserRoleId(2008, 1908, "/mis") 执行时间:104 UUID:c80f850a-dc2c-429e-b48a-ab06db257ccd
2016-01-18 18:38:55 - 执行的方法:IBaseMessageReceiveBO.getSysNotice({"dataIds":null,"emptyMsg":true,"list":[],"pageno":1,"rowsize":7,"start":0,"total":0,"totalrows":0}, 10011) 执行时间:114 UUID:a546b4e9-c440-44d2-85e8-d9c433c5095b
2016-01-18 18:38:55 - 执行的方法:IJbpmBO.findMyTaskList({"dataIds":null,"emptyMsg":true,"list":[],"pageno":1,"rowsize":10,"start":0,"total":0,"totalrows":0}, "10011", ) 执行时间:31 UUID:3556b1d7-c1e6-48f9-8c83-ddb803afd6d9
2016-01-18 18:38:55 - 执行的方法:IBaseMessageReceiveBO.getUnReadMsgCount(3, net.uni.in1.model.User@6a056bd9) 执行时间:77 UUID:9cbb02b9-d3ca-49b6-8383-260e86c18da6
2016-01-18 18:39:00 - 执行的方法:IFunctionBO.findAllUserFunction(10011) 执行时间:5194 UUID:8cb81140-8e8b-4d8a-92e9-94e6df051d54
2016-01-18 18:39:00 - 执行的方法:CsSuppAddCutDateDetAction.verifySupplierLoginHref() 执行时间:6465 UUID:8cb81140-8e8b-4d8a-92e9-94e6df051d54
2016-01-18 18:39:00 - 执行的方法:CsSuppAddCutDateDetAction.getFlag() 执行时间:0 UUID:8cb81140-8e8b-4d8a-92e9-94e6df051d54
一个线程一个唯一的UUID 根据UUID即可知道方法的轨迹信息
使用代理明显感觉项目启动过程变慢,暂时无法解决
监控到的方法中参数已经JSON化
后续会将输入的DEBUG日志统一输出到日志文件系统,方便调试问题