package org.nutz.ioc.aop.impl;
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.lang.Mirror;
import org.nutz.log.Log;
import org.nutz.log.Logs;
/**
* 通过AopConfigration来识别需要拦截的方法,并根据需要生成新的类
*
* @author zozoh(zozohtnt@gmail.com)
* @author Wendal(wendal1985@gmail.com)
*/
public class DefaultMirrorFactory implements MirrorFactory {
private static final Log log = Logs.get();
private Ioc ioc;
private ClassDefiner cd;
private AopConfigration aopConfigration;
private static final Object lock = new 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)
|| AopConfigration.IOCNAME.equals(name)
|| AopConfigration.class.isAssignableFrom(type)) {
return Mirror.me(type);
}
if (aopConfigration == null)
if (ioc.has(AopConfigration.IOCNAME))
aopConfigration = ioc.get(AopConfigration.class, AopConfigration.IOCNAME);
else
aopConfigration = new AnnotationAopConfigration();
List<InterceptorPair> interceptorPairs = aopConfigration.getInterceptorPairList(ioc, type);
if (interceptorPairs == null || interceptorPairs.size() < 1) {
if (log.isDebugEnabled())
log.debugf("%s , no config to enable AOP.", type);
return Mirror.me(type);
}
synchronized (lock) {
// 这段代码的由来:
// 当用户把nutz.jar放到java.ext.dirs下面时,DefaultMirrorFactory的classloader将无法获取用户的类
if (cd == null) {
ClassLoader classLoader = type.getClassLoader();
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null)
classLoader = getClass().getClassLoader();
}
log.info("Use as AOP ClassLoader parent : " + classLoader);
DefaultClassDefiner.init(classLoader);
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.aopConfigration = aopConfigration;
}
}