package org.nutz.ioc.aop.impl; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.nutz.aop.ClassAgent; import org.nutz.aop.ClassDefiner; import org.nutz.aop.DefaultClassDefiner; import org.nutz.aop.MethodInterceptor; import org.nutz.aop.asm.AsmClassAgent; import org.nutz.ioc.Ioc; import org.nutz.ioc.aop.MirrorFactory; import org.nutz.ioc.aop.config.AopConfigration; import org.nutz.ioc.aop.config.InterceptorPair; import org.nutz.ioc.aop.config.impl.AnnotationAopConfigration; import org.nutz.ioc.aop.config.impl.ComboAopConfigration; import org.nutz.lang.Mirror; import org.nutz.lang.util.AbstractLifeCycle; import org.nutz.log.Log; import org.nutz.log.Logs; /** * 通过AopConfigration来识别需要拦截的方法,并根据需要生成新的类 * * @author zozoh(zozohtnt@gmail.com) * @author Wendal(wendal1985@gmail.com) */ public class DefaultMirrorFactory extends AbstractLifeCycle implements MirrorFactory { private static final Log log = Logs.get(); private Ioc ioc; private ClassDefiner cd; private List<AopConfigration> list; private static final Object lock = new Object(); public ThreadLocal<Object> L = new ThreadLocal<Object>(); public DefaultMirrorFactory(Ioc ioc) { this.ioc = ioc; } public <T> Mirror<T> getMirror(Class<T> type, String name) { if (MethodInterceptor.class.isAssignableFrom(type) || type.getName().endsWith(ClassAgent.CLASSNAME_SUFFIX) || (name != null && name.startsWith(AopConfigration.IOCNAME)) || AopConfigration.class.isAssignableFrom(type) || Modifier.isAbstract(type.getModifiers())) { return Mirror.me(type); } if (L.get() != null) { log.info("skip aop check , type="+type.getName()); return Mirror.me(type); } if (list == null) init(); List<InterceptorPair> interceptorPairs = new ArrayList<InterceptorPair>(); for (AopConfigration cnf : list) { List<InterceptorPair> tmp = cnf.getInterceptorPairList(ioc, type); if (tmp != null && tmp.size() > 0) interceptorPairs.addAll(tmp); } if (interceptorPairs.isEmpty()) { if (log.isDebugEnabled()) log.debugf("Load %s without AOP", type); return Mirror.me(type); } int mod = type.getModifiers(); if (Modifier.isFinal(mod) || Modifier.isAbstract(mod)) { log.infof("[%s] configure to use AOP, but it is final/abstract, skip it", type.getName()); return Mirror.me(type); } synchronized (lock) { if (cd == null) { cd = DefaultClassDefiner.defaultOne(); } ClassAgent agent = new AsmClassAgent(); for (InterceptorPair interceptorPair : interceptorPairs) agent.addInterceptor(interceptorPair.getMethodMatcher(), interceptorPair.getMethodInterceptor()); return Mirror.me(agent.define(cd, type)); } } public void setAopConfigration(AopConfigration aopConfigration) { this.list = new ArrayList<AopConfigration>(); this.list.add(aopConfigration); } public void init() { if (this.ioc == null) return; if (this.list != null) return; if (L.get() != null) return; ArrayList<AopConfigration> list = new ArrayList<AopConfigration>(); try { L.set(Integer.TYPE); boolean flag = true; String[] names = ioc.getNames(); Arrays.sort(names); for (String beanName : names) { if (!beanName.startsWith(AopConfigration.IOCNAME)) continue; AopConfigration cnf = ioc.get(AopConfigration.class, beanName); list.add(cnf); if (cnf instanceof AnnotationAopConfigration) flag = false; if (cnf instanceof ComboAopConfigration) { if (((ComboAopConfigration) cnf).hasAnnotationAop()) { flag = false; } } } if (flag) list.add(new AnnotationAopConfigration()); this.list = list; } finally { L.set(null); } } }