package nebula.data.impl; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import nebula.data.Broker; import nebula.data.BrokerHandler; import nebula.lang.NebulaClassLoader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import com.google.common.collect.ImmutableMap; public class BrokerBuilder { Log log = LogFactory.getLog(getClass()); Map<String, BrokerInstanceBuilder> knownBrokeres; final BrokerInstanceBuilderClassMaker instanceBuilder; ReentrantLock lock = new ReentrantLock(); public BrokerBuilder() { knownBrokeres = ImmutableMap.of(); instanceBuilder = new BrokerInstanceBuilderClassMaker(); } public void clear(){ knownBrokeres = ImmutableMap.of(); } static int count = 0; public <T> T builder(Class<?> target) { BrokerInstanceBuilder builder = knownBrokeres.get(target.getName()); if (builder != null) { Broker<T> broker = builder.build(); return broker.get(); } lock.lock(); try { builder = knownBrokeres.get(target.getName()); if (builder != null) { Broker<T> broker = builder.build(); return broker.get(); } count++; String typeName = target.getName() + "_BrokerAuto" + count; // 构建代理类 { String innerTypeName = typeName.replace('.', '/'); ClassReader cr = new ClassReader(target.getName()); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); ClassVisitor bw; if(target.isInterface()){ bw= new BrokerForInterfaceClassVisitor(Opcodes.ASM4, cw, innerTypeName); }else{ target.getConstructor(); bw= new BrokerForClassClassVisitor(Opcodes.ASM4, cw, innerTypeName); } cr.accept(bw, ClassReader.SKIP_CODE); byte[] code = cw.toByteArray(); if (log.isDebugEnabled()) { try { String filename = "tmp/" + typeName + ".class"; String path = filename.substring(0, filename.lastIndexOf('/')); File file = new File(path); if (!file.exists()) { file.mkdir(); } new FileOutputStream(filename).write(code); } catch (FileNotFoundException e) { log.error(e); throw new RuntimeException(e); } } Class<?> clzBroker = NebulaClassLoader.defineClass(typeName, code); NebulaClassLoader.doResolveClass(clzBroker); } // 构建代理构建类,主要是为了性能,避免每次都是用Class.newInstance() 来构建代理 { String builderTypeName = typeName + "_Builder"; byte[] codeBuilder = instanceBuilder.dump(typeName,builderTypeName); if (log.isDebugEnabled()) { try { String filename = "tmp/" + builderTypeName + ".class"; String path = filename.substring(0, filename.lastIndexOf('/')); File file = new File(path); if (!file.exists()) { file.mkdir(); } new FileOutputStream(filename).write(codeBuilder); } catch (FileNotFoundException e) { log.error(e); throw new RuntimeException(e); } } Class<?> clzBuilder = NebulaClassLoader.defineClass(builderTypeName, codeBuilder); builder = (BrokerInstanceBuilder) clzBuilder.newInstance(); } ImmutableMap.Builder<String, BrokerInstanceBuilder> mapBuilder = ImmutableMap.builder(); this.knownBrokeres = mapBuilder.putAll(knownBrokeres).put(target.getName(), builder).build(); BrokerHandler<T> broker = builder.build(); return broker.get(); } catch (ClassFormatError e) { log.error(e); throw new RuntimeException(e); } catch (IOException e) { log.error(e); throw new RuntimeException(e); } catch (InstantiationException e) { log.error(e); throw new RuntimeException(e); } catch (IllegalAccessException e) { log.error(e); throw new RuntimeException(e); } catch (SecurityException e) { log.error(e); throw new RuntimeException(e); } catch (NoSuchMethodException e) { log.error(e); throw new RuntimeException("Must has default constructor",e); } finally { lock.unlock(); } } }