黑马程序员—(JAVA)类加载器、代理

发布时间:2014-10-23 23:25:48
来源:分享查询网

------- android培训、java培训、期待与您交流! ----------  类加载器 类加载器:专门把类加载进内存的工具,用到一个类,首先应该把它加载进内存,那么这些工作就由加载器完成。     Java虚拟机中可以安装多个类加载器,系统默认的加载器有三个:BootStrap、ExtClassLoader、AppClassLoader;每个负责加载特定位置的类。     类加载器本身也是Java类,类加载器也要被其他的类加载器加载,但BootStrap不是一个类,所以不需要被别的类加载,它是一个嵌套在JVM内核中的,JVM一启动它就加载进内存、用C++编写的一段二进制代码。 Java虚拟机中的所有类加载器都是采用父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载。 类加载器的委托机制:每个类加载器加载类时,先委托给其上级类加载器;当所有的祖宗类加载器都没有加载到类时,回到发起者加载器,如果还是加载不了,则抛出ClassNotFoundException,而不会去找发起者的子类加载器。  每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异常。  模板方法设计模式:总的流程已经在父类中确定好了,而流程中的一些细节父类无法确定,留给子类去完成。那么子类只要复写父类的方法,给出具体的操作细节即可,这就是模板方法设计模式。     自定义一个类加载器的步骤:     1、自定义的类加载器必须继承抽象类ClassLoader;     2、loadClass方法,把类名传给该函数,它就会去加载这个类,并且返回一个class字节码。loadClass方法会先去找父类加载器,接着找findClass方法。     3、所以只要复写findClass方法就可以了,loadClass方法中封装的加载器的委托流程,我们要做的就是在findClass方法中给出具体实现。     4、defineClass方法,可以通过该方法将得到的class文件的内容转换成为字节码。 代理     代理:要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能,则编写一个与目标类具有相同接口的代理类;代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码;这就是代理的基本体现。     作用:如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类,这样方便于切换。譬如:想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,想去掉系统功能也很容易。 AOP:交叉业务编程的问题即为面向方面的编程(AOP),AOP的目标就是要使交叉业务模块化。可以将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。代理是实现AOP功能的核心和关键技术。     动态代理技术:JVM可以在运行期动态生成类的字节码,这个动态生成的类往往被用作代理类,即动态代理类,API为类Proxy。     JVM生成的动态代理类必须实现一个或者多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。     代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理的方法中添加上一些系统的代码。     位置:1、在调用目标方法之前;2、在调用目标方法之后;3、在调用目标方法前后;           4、在处理目标方法异常的catch块中。     创建动态类及其实例对象:1、类加载器;2、接口;3、生成的类中的方法怎样,由我们提供,把我们的代码写在一个约定好的接口对象的方法中(类InvocationHandler中的invoke方法),把对象传给它,它调用我们的方法,相当于插入了我们的代码,提供执行代码的对象就是那个InvocationHandler对象,它是在创建动态类的实例对象的构造方法时传递进去的。在上面的InvocationHandler对象的invoke方法中加一点代码,就可以看到这些代码被调用运行了。     动态代理的工作原理:客户端调用代理,代理的构造方法接收一个InvocationHandler对象;然后客户端调用代理的各个方法时,代理会把各个请求转发给成员变量InvocationHandler,然后InvocationHandler对象又把请求分发给目标的相应方法,并在InvocationHandler的invoke方法中可以增加额外的功能。    增加的功能不能写死,要灵活使用。可以把额外的功能封装成为一个类,这个类中的方法封装了额外的功能,并把这个类的对象传递到InvocationHandler的invoke方法中,调用这个类中的方法,那么就相当于增加了额外功能。传对象,在代理中调用该对象的方法,这就是面向切面的编程。执行了对象的方法,就相当于执行了切面的方法。 工厂类BeanFactory负责创建目标类或者代理类的实例对象,并通过配置文件实现切换,不必要改动源代码。它的getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。     ProxyFactoryBean充当封装生成动态代理的工厂,需要为工厂提供目标,建议等参数信息。    想要代理,可以在配置文件中配;不想要代理,也可以在配置文件中配,这就是Spring的精髓! 总结 这部分还没有真正的理解,暂时做个记录。

返回顶部
查看电脑版