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

wordpress知更鸟打赏seo服务销售招聘

wordpress知更鸟打赏,seo服务销售招聘,姓名域名网站,关于公司网站建设请示动态代理: 由程序帮助我们生成类,不需要我们自己手动写。 常规实现方式 有一个接口: 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/337655.html

相关文章:

  • 网站页脚版权信息长沙互联网网站建设
  • 做佣金单网站semester是什么意思
  • 做电影网站程序好用现在的网络推广怎么做
  • 免费查企业app排行榜涟源网站seo
  • 儿童摄影网站建设百度品牌广告收费标准
  • wordpress防止攻击wifi优化大师下载
  • 自适应企业网站用什么框架做海淀搜索引擎优化seo
  • 企业网站改版方案郑州网站推广培训
  • banner图片怎么设计网站高端营销型网站
  • 视频解析接口网站怎么做小红书广告投放平台
  • 网站建设 推广 公司seo解释
  • 网站建设要哪些人?百度竞价排名服务
  • 湘潭网站建设设计手机制作网站app
  • 网站设计 字体seo站内优化
  • 网站对一个关键词做排名怎么做跨境电商营销推广
  • 北京做电商网站设计互联网营销的方法有哪些
  • 广州建网站哪儿济南兴田德润简介百度手机怎么刷排名多少钱
  • 做网站 需要工信部备案吗河北百度seo点击软件
  • 商务网站开发与建设论文线上推广策略
  • 深圳知名网站建设公司谷歌搜索引擎为什么国内用不了
  • 南宁网站建设找建站通seo网站优化系统
  • 做网站哪一家公司好seo综合查询平台官网
  • 集团网站建设特点助君韶山seo快速排名
  • 网站公安备案网址网络推广计划制定步骤
  • 网站开发图片加载过慢如何优化如何开发一个网站
  • 涿州网站建设天峰推广团队
  • 功能型网站多少钱电商sem是什么意思
  • 一级a做爰片2202网站seo关键词排名优化推荐
  • 洛阳网站设计开发东莞企业网站排名
  • 传统门户网站有哪些百度推广电话