学生聚合成了班级,班级没有学生,学生有多少都不影响他是一个班级。轮子,发动机,车架组合成了汽车。少了任何一个部件汽车都是不完整的。组合的依赖性更强。
取得该Class对象的类装载器。ClassLoader负责载入系统的所有Resources,通过ClassLoader从而将资源载入JVM,每个class都有一个引用,指向自己的ClassLoader。
同学你好,这里的super指的是Object类,这个Object类是所有类的超类(也称为父类)。
所有类的对象都实现这个Object类的方法。
以下就是本课的示例代码里
package com.imooc.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LogHandler implements InvocationHandler {
private Object target;
public LogHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 日志开始
System.out.println("日志开始...");
method.invoke(target);
// 日志结束
System.out.println("日志结束...");
return null;
}
}
第一种方法
Car car = new Car();
Class carClass = car.getClass();
InvocationHandler timeHandler = new TimeHandler(car);
Moveable proxy = (Moveable) Proxy.newProxyInstance(carClass.getClassLoader(),
carClass.getInterfaces(),timeHandler);
InvocationHandler logHandler = new LogHandler(proxy);
Moveable proxy2 = (Moveable) Proxy.newProxyInstance(proxy.getClass().getClassLoader(),
proxy.getClass().getInterfaces(), logHandler);
proxy2.move();
第二种方法
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> cls = car.getClass();
/**
* loader 类加载器
* interfaces 实现接口
* h InvocationHandler
*/
Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),
cls.getInterfaces(), h);
InvocationHandler h2=new LogHandler(m);
Class<?> clh=m.getClass();
Moveable m2=(Moveable)Proxy.newProxyInstance(clh.getClassLoader(),
clh.getInterfaces(), h2);
m2.move();
其实都差不多。。。
编程思想时通用的!
老师剪切了。
构造器就是构造方法,还有人叫构造函数,至于为什么不统一呢,只能翻译背锅吧。
mTime是对car的时间代理对象,再生成mLog即mTime的日志代理对象即可。
Car car=new Car(); InvocationHandler timeHandler =new TimeHandler(car); Moveable m=(Moveable)Proxy.newProxyInstance(car.getClass().getClassLoader(),car.getClass().getInterfaces(),timeHandler); InvocationHandler logHandler=new LogHandler(m); Moveable m1=(Moveable)Proxy.newProxyInstance(m.getClass().getClassLoader(),m.getClass().getInterfaces(),logHandler); m1.move();
D:\eclipse\workspace\Proxy/bin/com/sxw/simulationJdkProxy/$Proxy0.java
这个目录我感觉不大对
是代理对象,可以在invoke方法中打印一下。
System.out.println(porxy.getClass().getName());
会输出com.imooc.....$Proxy0
题主的方法解决了我的问题,感谢
@CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException{ ... return cons.newInstance(new Object[]{h}); } 这个方法返回的是一个对象,一个动态生成的代理类的对象,moveable.getClass().getName()得到的是动态生成的这个代理类的名字。
method.invoke(target)=====target.method
这是静态代理,生成代理对象时就要传入被代理对象.这是没有引入handle时,实现的代理原理.
解决了吗,同问
解决了
想多了,后面执行m.move()或m.stop()就行了,代理类并不关心要实现谁
通过java反射技术,使得被代理类与生成的代理类拥有相同的接口,只不过两个类对接口中的实现方法不同,代理类中的方法就是对被代理类中的方法的一个增强。既然涉及到反射,那么具体调用哪个方法就是在运行时才能确定,你运行时调用哪个,它就执行哪个
随着业务逻辑的不断增多,功能的增加,使用继承方式增加功能会导致类爆炸。
使用代理实现的话,更加灵活,易于拓展
首先this指代的是当前类的对象。当前类是cglibProxy,所以this指代是cglibProxy类的对象。
当前类应该容易理解当前声明的类。想了解更多继续看。
官方文档: this 称为隐式参数。
这个应用应该见过:
public class Student {
private String name;
public void setName(String n) {
name = n;
}
}
Student stu = new Student();
stu.setName("siri") 他的执行过程是这样的stu.name="siri";
stu是name的隐式参数(即调用此方法的对象) 用关键字this表示
相对应的 String n ,n 称为方法的显示参数。
隐式参数一般用写,当方法的局部变量和类的成员变量发生冲突是必须
用隐式参数如
setName(Stirng name) {
name = name;//error
this.name = name //right this 代表调用此方法的对象
}
-----------------------------------------
问题已解决:
1、在生成java文件的时候,java文件路径不正确;
我写的是:
String filename = System.getProperty("user.dir")+"/com/design/proxy/$Proxy0.java";
但是我的编译器正式输出路径为:
String filename = System.getProperty("user.dir")+"/target/classes/com/design/proxy/$Proxy0.java";
总结:
需要确认Tomcat启动时查找class的路径是否和上面java文件的路径一致,因为编译java文件的class文件也会在此处,所以编译后的class不在Tomcat查找的位置则会报ClassNotFoundException;
因为接口中可能不止一个方法,所以要遍历一下接口中的所有方法并且全部保存到一个字符串中