背景:
设计模式开始学习工厂部分,分别为简单工厂,工厂方法,抽象工厂,目前的进度是学习到工厂方法,但是工厂方法需要手写加减乘除四个工厂,因为代码的重复性比较高,这些代码是不是能让机器来写呢?机器写好以后能不能直接让程序不停,根据传参可以生成类,并且执行方法呢?这一切都要依赖反射。
首先是实现自动生成工厂代码
思路:
1、写模板类(四个工厂,还有四个工厂客户端)
2、生成新类的时候替换其中的关键字即可。
下面是主函数中的东西:
Scanner scanner = new Scanner(System.in); System.out.println("请输入要创建的算法的模式:"); className = scanner.nextLine(); String srcFactoryCode = "package MoreAutoFactory;\n" + "public class" + " " + className + "Factory" + " " + "implements IFactory {\n" + " @Override\n" + " public Operation createOperation() {\n" + " return new" + " " + "Operation"+className + "();\n" + " }\n" + "}"; //要创建文件的路径 String path = "E:\\zy\\TGB-zgy-2022\\米老师设计模式课相关资料必须留着\\米老师设计模式课小例子\\JAVAtest\\Factory\\src\\main\\java\\MoreAutoFactory\\" + className + "Factory.java"; File file = new File(path); if (!file.exists()) { if (file.createNewFile()) { System.out.println("新类型工厂文件创建成功"); FileWriter fileWriter = new FileWriter(path); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(srcFactoryCode); bufferedWriter.close(); //编译文件 Compiler(System.getProperty("user.dir")+"\\Factory\\target\\classes",path); } } String srcClientCode = "package MoreAutoFactory;\n" + "public class" + " " + className + "Client" + " {\n" + " public void getEndResult() throws Exception {\n" + " IFactory operFactory = new " + className + "Factory();\n" + " Operation oper = operFactory.createOperation();\n" + " oper.setNumberA(2);\n" + " oper.setNumberB(2);\n" + " double result = oper.getResult();\n " + " System.out.println(result);\n" + " }\n" + "}"; //要创建文件的路径 String pathClient = "E:\\zy\\TGB-zgy-2022\\米老师设计模式课相关资料必须留着\\米老师设计模式课小例子\\JAVAtest\\Factory\\src\\main\\java\\MoreAutoFactory\\" + className + "Client.java"; File fileClient = new File(pathClient); if (!fileClient.exists()) { if (fileClient.createNewFile()) { System.out.println("新类型客户端文件创建成功"); FileWriter fileWriter = new FileWriter(pathClient); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(srcClientCode); bufferedWriter.close(); //编译文件 Compiler(System.getProperty("user.dir")+"\\Factory\\target\\classes",pathClient); } } }
实现热加载
下面自定义类加载器
public class MyClasslLoader extends ClassLoader { /** 要加载的 Java 类的 classpath 路径 */ private String classpath; public MyClasslLoader(String classpath) { // 指定父加载器 super(ClassLoader.getSystemClassLoader()); this.classpath = classpath; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] data = this.loadClassData(name); return this.defineClass(name, data, 0, data.length); } /** * 加载 class 文件中的内容 * * @param name * @return */ private byte[] loadClassData(String name) { try { // 传进来是带包名的 name = name.replace(".", "//"); FileInputStream inputStream = new FileInputStream(new File(classpath + name + ".class")); // 定义字节数组输出流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); int b = 0; while ((b = inputStream.read()) != -1) { baos.write(b); } inputStream.close(); return baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return null; } }
定义要实现热加载的类的接口
public interface BaseManager { public void logic() throws IOException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException; }
定义实现类
public class MyManager implements BaseManager { @Override public void logic() throws IOException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { create(); reflect(); } // System.out.println(LocalTime.now() + ": Java类的热加载"); static String className = ""; static String operationName = ""; public static void create() throws IOException { Scanner scanner = new Scanner(System.in); System.out.println("请输入要创建的算法的模式:"); className = scanner.nextLine(); String srcFactoryCode = "package MoreAutoFactory;\n" + "public class" + " " + className + "Factory" + " " + "implements IFactory {\n" + " @Override\n" + " public Operation createOperation() {\n" + " return new" + " " + "Operation"+className + "();\n" + " }\n" + "}"; //要创建文件的路径 String path = "E:\\zy\\TGB-zgy-2022\\米老师设计模式课相关资料必须留着\\米老师设计模式课小例子\\JAVAtest\\Factory\\src\\main\\java\\MoreAutoFactory\\" + className + "Factory.java"; File file = new File(path); if (!file.exists()) { if (file.createNewFile()) { System.out.println("新类型工厂文件创建成功"); FileWriter fileWriter = new FileWriter(path); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(srcFactoryCode); bufferedWriter.close(); //编译文件 Compiler(System.getProperty("user.dir")+"\\Factory\\target\\classes",path); } } String srcClientCode = "package MoreAutoFactory;\n" + "public class" + " " + className + "Client" + " {\n" + " public void getEndResult() throws Exception {\n" + " IFactory operFactory = new " + className + "Factory();\n" + " Operation oper = operFactory.createOperation();\n" + " oper.setNumberA(2);\n" + " oper.setNumberB(2);\n" + " double result = oper.getResult();\n " + " System.out.println(result);\n" + " }\n" + "}"; //要创建文件的路径 String pathClient = "E:\\zy\\TGB-zgy-2022\\米老师设计模式课相关资料必须留着\\米老师设计模式课小例子\\JAVAtest\\Factory\\src\\main\\java\\MoreAutoFactory\\" + className + "Client.java"; File fileClient = new File(pathClient); if (!fileClient.exists()) { if (fileClient.createNewFile()) { System.out.println("新类型客户端文件创建成功"); FileWriter fileWriter = new FileWriter(pathClient); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(srcClientCode); bufferedWriter.close(); //编译文件 Compiler(System.getProperty("user.dir")+"\\Factory\\target\\classes",pathClient); } } } public static void reflect() throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { String str = "MoreAutoFactory."+className+"Client"; System.out.println(str); Class classClient = Class.forName("MoreAutoFactory."+className+"Client"); Object object = classClient.newInstance(); Method getEndResultMethod = classClient.getMethod("getEndResult"); getEndResultMethod.invoke(object,null); } public static void Compiler(String compilerPath,String javaPath){ JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); // int status = javac.run(null, null, null, "-d", System.getProperty("user.dir")+"\\target\\classes\\MoreAutoFactory","D:/test/AlTest.java"); int status = javac.run(null, null, null, "-d", compilerPath,javaPath); if(status!=0){ System.out.println("没有编译成功!"); } } }
public class MyClasslLoader extends ClassLoader { /** 要加载的 Java 类的 classpath 路径 */ private String classpath; public MyClasslLoader(String classpath) { // 指定父加载器 super(ClassLoader.getSystemClassLoader()); this.classpath = classpath; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] data = this.loadClassData(name); return this.defineClass(name, data, 0, data.length); } /** * 加载 class 文件中的内容 * * @param name * @return */ private byte[] loadClassData(String name) { try { // 传进来是带包名的 name = name.replace(".", "//"); FileInputStream inputStream = new FileInputStream(new File(classpath + name + ".class")); // 定义字节数组输出流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); int b = 0; while ((b = inputStream.read()) != -1) { baos.write(b); } inputStream.close(); return baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return null; } }
public class MsgHandle implements Runnable { @Override public void run() { while (true) { BaseManager manager = ManagerFactory.getManager(ManagerFactory.MY_MANAGER); try { manager.logic(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class ManagerFactory { /** 记录热加载类的加载信息 */ private static final Map<String, LoadInfo> loadTimeMap = new HashMap<>(); /** 要加载的类的 classpath */ public static final String CLASS_PATH = "E:\\zy\\TGB-zgy-2022\\米老师设计模式课相关资料必须留着\\米老师设计模式课小例子\\JAVAtest\\Factory\\target\\classes"; /** 实现热加载的类的全名称(包名+类名 ) */ public static final String MY_MANAGER = "hotLoad.MyManager"; public static BaseManager getManager(String className) { File loadFile = new File(CLASS_PATH + className.replaceAll("\\.", "/") + ".class"); // 获取最后一次修改时间 long lastModified = loadFile.lastModified(); System.out.println("当前的类时间:" + System.currentTimeMillis()); // loadTimeMap 不包含 ClassName 为 key 的信息,证明这个类没有被加载,要加载到 JVM if (loadTimeMap.get(className) == null) { load(className, lastModified); } // 加载类的时间戳变化了,我们同样要重新加载这个类到 JVM。 else if (loadTimeMap.get(className).getLoadTime() != lastModified) { load(className, lastModified); } return loadTimeMap.get(className).getManager(); } /** * 加载 class ,缓存到 loadTimeMap * * @param className * @param lastModified */ private static void load(String className, long lastModified) { MyClasslLoader myClasslLoader = new MyClasslLoader(className); Class loadClass = null; // 加载 try { loadClass = myClasslLoader.loadClass(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } BaseManager manager = newInstance(loadClass); LoadInfo loadInfo = new LoadInfo(myClasslLoader, lastModified); loadInfo.setManager(manager); loadTimeMap.put(className, loadInfo); } /** * 以反射的方式创建 BaseManager 的子类对象 * * @param loadClass * @return */ private static BaseManager newInstance(Class loadClass) { try { return (BaseManager)loadClass.getConstructor(new Class[] {}).newInstance(new Object[] {}); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; } }
public class LoadInfo { /** 自定义的类加载器 */ private MyClasslLoader myClasslLoader; /** 记录要加载的类的时间戳-->加载的时间 */ private long loadTime; /** 需要被热加载的类 */ private BaseManager manager; public LoadInfo(MyClasslLoader myClasslLoader, long loadTime) { this.myClasslLoader = myClasslLoader; this.loadTime = loadTime; } public MyClasslLoader getMyClasslLoader() { return myClasslLoader; } public void setMyClasslLoader(MyClasslLoader myClasslLoader) { this.myClasslLoader = myClasslLoader; } public long getLoadTime() { return loadTime; } public void setLoadTime(long loadTime) { this.loadTime = loadTime; } public BaseManager getManager() { return manager; } public void setManager(BaseManager manager) { this.manager = manager; } }
public class ClassLoadTest { public static void main(String[] args) { new Thread(new MsgHandle()).start(); } }
预知后事如何,请听下回分解。