当前位置: 首页 > wzjs >正文

记事本做网站怎么改字体中国域名后缀

记事本做网站怎么改字体,中国域名后缀,宁波网络营销外包推广,泰安高新区人才招聘网动态代理: 由程序帮助我们生成类,不需要我们自己手动写。 常规实现方式 有一个接口: package proxy;public interface MyInterface {void fun1();void fun2();void fun3();}需求 1 :添加一个类,实现接口&#xff0c…

动态代理: 由程序帮助我们生成类,不需要我们自己手动写。

常规实现方式

有一个接口:

package proxy;public interface MyInterface {void fun1();void fun2();void fun3();}

需求 1 :添加一个类,实现接口,方法主体是 打印方法名。

于是你写了 NameImpl 类:

package proxy;public class NameImpl implements MyInterface{@Overridepublic void fun1() {System.out.println("fun1");}@Overridepublic void fun2() {System.out.println("fun2");}@Overridepublic void fun3() {System.out.println("fun3");}
}

需求 2 :添加一个类,实现接口,方法主体是 打印 方法名的长度。

于是你写了 NameLengthImpl 类:

package proxy;public class NameLengthImpl implements MyInterface{@Overridepublic void fun1() {String methodName = "fun1";System.out.println(methodName);System.out.println(methodName.length());}@Overridepublic void fun2() {String methodName = "fun2";System.out.println(methodName);System.out.println(methodName.length());}@Overridepublic void fun3() {String methodName = "fun3";System.out.println(methodName);System.out.println(methodName.length());}
}

是否可以 动态 创建类?

思考一个问题:上述的需求都是根据 方法的名字 做一些操作,那我们是否可以动态地创建一些类?

可以的。无非就是用程序 写一个文件,使之符合 Java 文件规范。

生成 .java 文件

public class MyInterfaceFactory {public static File createJavaFile() throws IOException {String context = """package proxy;public class NameImpl implements MyInterface{@Overridepublic void fun1() {System.out.println("fun1");}@Overridepublic void fun2() {System.out.println("fun2");}@Overridepublic void fun3() {System.out.println("fun3");}}""";File javaFile = new File("NameImpl.java");Files.writeString(javaFile.toPath(),context);return javaFile;}public static void main(String[] args) throws IOException {createJavaFile();}
}

运行完之后,出现

我们成功用代码,动态地生成了一个类。

问题 1:虚拟机只能运行 .class 文件,生成的 .java 文件 JVM 如何运行?

  • 在程序运行的时候,编译这个文件。

问题 2:一个类中,哪些东西是动态的,哪些是是不变的?

  • 假设 类中的包名,实现的接口 是不变的。
  • 类名、函数体 是动态的。
package proxy;
public class Compiler {public static void compile(File javaFile) {JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();try(StandardJavaFileManager fileManager =compiler.getStandardFileManager(null,null,null)){Iterable<? extends JavaFileObject> compilerUnits =fileManager.getJavaFileObjectsFromFiles(List.of(javaFile));// 设置编译选项 (指定编译路径)List<String> options = Arrays.asList("-d", "./out/production/LXDemo");JavaCompiler.CompilationTask compilerTask =compiler.getTask(null, fileManager, null, options, null, compilerUnits);Boolean success = compilerTask.call();if (success){System.out.println("编译成功");}else {System.out.println("编译失败");}} catch (IOException e) {throw new RuntimeException(e);}}
}

上述代码作用:编译 .java 文件 到 classPath 路径。

类名、函数体如何是动态的呢?

package proxy;
public class MyInterfaceFactory {public static File createJavaFile() throws IOException {// 动态获取类名String className = getClassName();// 动态获取函数体String funBody1 = functionBody("fun1");String funBody2 = functionBody("fun2");String funBody3 = functionBody("fun3");String context = "package proxy;\n" +"\n" +"public class "+ className +" implements MyInterface{\n" +"    @Override\n" +"    public void fun1() {\n" +"        "+funBody1+"\n" +"    }\n" +"\n" +"    @Override\n" +"    public void fun2() {\n" +"        "+funBody2+"\n" +"    }\n" +"\n" +"    @Override\n" +"    public void fun3() {\n" +"        "+funBody3+"\n" +"    }\n" +"}\n";File javaFile = new File(className + ".java");Files.writeString(javaFile.toPath(),context);return javaFile;}private static String functionBody(String methodName) {return "System.out.println(\"" + methodName +"\");";}private static final AtomicInteger count = new AtomicInteger(0);private static String getClassName() {return "MyInterface$proxy" + count.incrementAndGet();}public static void main(String[] args) throws IOException {File javaFile = createJavaFile();Compiler.compile(javaFile);}
}

编译完之后,我们是不是可以使用 类加载器 ,把 .class 文件加载到虚拟机中。

// 加载类、反射构造对象
private static MyInterface newInstance(String className) throws Exception {Class<?> aClass = MyInterfaceFactory.class.getClassLoader().loadClass(className);Constructor<?> constructor = aClass.getConstructor();MyInterface instance = (MyInterface)constructor.newInstance();return instance;
}

程序运行时,编译.java文件

就这样我们 使用代码,创建了一个类,编译它,并加载到 JVM 中,获取对象。

我们创建了一个原本 .java 中没有的类,是程序在运行时,帮助我们创建的。

package proxy;
public class MyInterfaceFactory {private static File createJavaFile(String className) throws IOException {String funBody1 = functionBody("fun1");String funBody2 = functionBody("fun2");String funBody3 = functionBody("fun3");String context = "package proxy;\n" +"\n" +"public class "+ className +" implements MyInterface{\n" +"    @Override\n" +"    public void fun1() {\n" +"        "+funBody1+"\n" +"    }\n" +"\n" +"    @Override\n" +"    public void fun2() {\n" +"        "+funBody2+"\n" +"    }\n" +"\n" +"    @Override\n" +"    public void fun3() {\n" +"        "+funBody3+"\n" +"    }\n" +"}\n";File javaFile = new File(className + ".java");Files.writeString(javaFile.toPath(),context);return javaFile;}private static String functionBody(String methodName) {return "System.out.println(\"" + methodName +"\");";}private static final AtomicInteger count = new AtomicInteger(0);private static String getClassName() {return "MyInterface$proxy" + count.incrementAndGet();}private static MyInterface newInstance(String className) throws Exception {Class<?> aClass = MyInterfaceFactory.class.getClassLoader().loadClass(className);Constructor<?> constructor = aClass.getConstructor();MyInterface instance = (MyInterface)constructor.newInstance();return instance;}public static MyInterface createProxyObject() throws Exception {String className = getClassName();// 创建 .java文件File javaFile = createJavaFile(className);// 编译Compiler.compile(javaFile);// 加载、创建对象return newInstance("proxy." + className);}
}public class Main {public static void main(String[] args) throws Exception {MyInterface obj = MyInterfaceFactory.createProxyObject();obj.fun1();obj.fun2();obj.fun3();}
}

问题:functionBody() 返回的 方法体 是固定的,不能满足我们需求

  • 写一个 MyHandle 接口,具体实现交给使用者。
    • 让使用者 自己传入 方法体。

动态生成 方法体

现在我不固定方法体,而是让 开发者 实现。

动态生成的类 要求实现:

  • 打印 方法名
    • System.out.println("fun1");
  • 打印 1;打印 方法名
System.out.println(1);
System.out.println("fun1");
  • 包装一个 MyInterface
MyInterface myInterface;public void fun1() {System.out.println("before");myInterface.fun1();System.out.println("after");
}

最终的实现:

public interface MyHandle {// 根据方法名,返回方法体String methodBody(String methodName);// set proxy的myInterfacedefault void setMyInterface(MyInterface proxy) throws Exception {}
}public class MyInterfaceFactory {private static File createJavaFile(String className,MyHandle myHandle) throws IOException {String funBody1 = myHandle.methodBody("fun1");String funBody2 = myHandle.methodBody("fun2");String funBody3 = myHandle.methodBody("fun3");String context = "package proxy;\n" +"\n" +"public class "+ className +" implements MyInterface{\n" +"    MyInterface myInterface;\n"+"    @Override\n" +"    public void fun1() {\n" +"        "+funBody1+"\n" +"    }\n" +"\n" +"    @Override\n" +"    public void fun2() {\n" +"        "+funBody2+"\n" +"    }\n" +"\n" +"    @Override\n" +"    public void fun3() {\n" +"        "+funBody3+"\n" +"    }\n" +"}\n";File javaFile = new File(className + ".java");Files.writeString(javaFile.toPath(),context);return javaFile;}private static final AtomicInteger count = new AtomicInteger(0);private static String getClassName() {return "MyInterface$proxy" + count.incrementAndGet();}private static MyInterface newInstance(String className,MyHandle myHandle) throws Exception {Class<?> aClass = MyInterfaceFactory.class.getClassLoader().loadClass(className);Constructor<?> constructor = aClass.getConstructor();MyInterface proxy = (MyInterface)constructor.newInstance();// 给对象赋值myHandle.setMyInterface(proxy);return proxy;}public static MyInterface createProxyObject(MyHandle myHandle) throws Exception {String className = getClassName();File javaFile = createJavaFile(className,myHandle);Compiler.compile(javaFile);return newInstance("proxy." + className,myHandle);}
}
public class Main {public static void main(String[] args) throws Exception {MyInterface proxy1 = MyInterfaceFactory.createProxyObject(new MyHandleImpl1());proxy1.fun1();proxy1.fun2();proxy1.fun3();System.out.println("-----");MyInterface proxy2 = MyInterfaceFactory.createProxyObject(new MyHandleImpl2());proxy2.fun1();proxy2.fun2();proxy2.fun3();System.out.println("-----");MyInterface logProxy = MyInterfaceFactory.createProxyObject(new LogHandle(proxy1));logProxy.fun1();logProxy.fun2();logProxy.fun3();}// 打印方法名private static class MyHandleImpl1 implements MyHandle{@Overridepublic String methodBody(String methodName) {return "System.out.println(\"" + methodName + "\");";}}// 打印1,打印方法名private static class MyHandleImpl2 implements MyHandle{@Overridepublic String methodBody(String methodName) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("System.out.println(1);").append("\n").append("System.out.println(\"" + methodName + "\");");return stringBuilder.toString();}}// 包装myInterface,private static class LogHandle implements MyHandle{@Overridepublic String methodBody(String methodName) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("System.out.println(\"before\");\n").append("myInterface."+ methodName +"();\n").append("System.out.println(\"after\");");return stringBuilder.toString();}private final MyInterface myInterface;public LogHandle(MyInterface myInterface){this.myInterface = myInterface;}@Overridepublic void setMyInterface(MyInterface proxy) throws Exception {Class<? extends MyInterface> aClass = proxy.getClass();Field field = aClass.getDeclaredField("myInterface");field.set(proxy,myInterface);}}}
// out:
// 编译成功
// fun1
// fun2
// fun3
// -----
// 编译成功
// 1
// fun1
// 1
// fun2
// 1
// fun3
// -----
// 编译成功
// before
// fun1
// after
// before
// fun2
// after
// before
// fun3
// after

解释:因为并不是所有的 proxy 需要 setInterface。所以 setMyInterface()default

只有需要 setInterface 的 Handle 才去实现。

public interface MyHandle {String methodBody(String methodName);default void setMyInterface(MyInterface proxy) throws Exception {}
}

自己写的类:

动态代理生成的类:

编译完之后的字节码文件:

总结

我们是如何动态生成类的呢?

生成 .java 文件 -> 编译为字节码文件 -> ClassLoader 加载到 JVM -> 反射创建对象

不足:

  • 生成的类只能是 实现 MyInterface 接口的,不能动态地 传递接口。
  • 生成 .java 文件,再编译为 字节码文件。 而不是直接生成字节码文件。

Spring 中的事务

Spring 的事务底层是 AOP,AOP 底层是动态代理(反射生成)。

事务失效的本质: 动态代理失效了

http://www.dtcms.com/wzjs/798390.html

相关文章:

  • 抖音关键词推广怎么做一个新的网站怎么做优化
  • 开不锈钢公司怎么做网站重庆建筑工程
  • 北京网站优化wyhseo灵感中心素材网站
  • 长沙开福区专业制作网站卖车网站
  • 南平抖音搜索排名seo软件seo关键词词库
  • 网站建设目标文档wordpress文章分页付费
  • 最短的网站湖北省电力建设三公司网站
  • 农业网站建设费用预算php自适应网站开发
  • 教育网站都有哪些网站开发 毕业答辩ppt
  • qt 可以做网站吗h5制作
  • 佛山网站建设科技有限公司官方网站开发需要几个技术人员
  • 上传网站需要什么软件怎么做网站板块
  • 江西企业网站建设深圳装修设计生产厂家
  • 宜城网站定制葛亚曦设计公司官网
  • 做网站work什接网站制作
  • 上海专业做网站wordpress网站是什么意思
  • 集美网站开发兼职做猎头的网站
  • 郑州网站托管公司用记事本制作html网页代码
  • 太原在线网站建设wordpress仿商城
  • 黑龙江省城乡建设厅网站怎么自己做优惠券网站
  • 10个免费网站爱战网关键词挖掘
  • 天津武清做网站的公司凡客的意思
  • 怎样做古玩网站大宇网络潍坊网站建设
  • dnf怎么做辅助网站长春最专业的seo公司
  • 家电网站设计方案厦门黄页
  • 网站后台管理系统 源码模板网站开发
  • 宝应县城乡建设局网站wordpress插件cloud
  • 五金网站建设关键词挖掘工具
  • 赤峰建网站iis打开网站变成下载
  • 注册公司是在哪个网站站长统计幸福宝宝官方