黑马程序员之类加载器和动态代理

时间:2023-02-17 17:14:44
 

---------------------- android培训java培训、期待与您交流! ----------------------知道这一章东西比较难理解的,加油!

类加载器:java虚拟机中可以安装多个类加载器,系统默认的主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,appClassLoader

类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。

Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,

在实例化每个类加载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载

ClassLoader loader =ClassLoaderTest.class.getClassLoader();

While(loader!=null){

System.out.println(loader.getClass.getClass().getName());

loader=loader.getParent();

}

//委托机制:每个类加载器加载类时,又先委托给其上级类加载器,当所有的祖宗类加载器没有加载到类时,回到发起者类加载器,还加载不到就抛ClassNotFoundException,不会再去找下一级了

那么,如果我们写一个java.lang.*的话,就永远得不到加载,因为加载器的祖宗已经保存了这个类的字节码

自定义类加载器的编写:

//模板方法设计模式:

总体流程在父类中规定好了,具体的一些细节方法就由子类自己去编写

//类加载器的原理:覆盖findClass(),得到class文件对应的二进制通过defineClass()变成字节码

1.写一个加密文件:

Private static void cypher(InputStream ips,PutputStream ops){

int b=-1;

While(b=ips.read()!=-1){

Ops.write(b^0xff);

}

}

2.创建输入输出对象

String srcPath=args[0];

String destPath=args[1];

FileInputStream fis=new FileInputStream(srcPath);

FileOutputStream fos=new FileOutputStream(destPath);

cypher(fis,fos);

fis.close();

fos.close();

3.写一个加密的类

public class ClassLoaderAttachment extends Date{

public String toString(){

return “it315”;

}

}

然后用自己写的解密类加载器,要继承ClassLoader

覆盖他的findClass(String name)

高级类加载器:属于一个JavaWeb 的应用,属于javaEE,涉及到的一些内容需要加强

我们把Jar包放置的位置为bin,访问就成功了

代理:

也是一个类,在代理类中要调用目标类的方法,但是在方法的前后要加上系统的功能

如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类,还是代理类,这样以后就很容易切换,譬如:想要日志功能时就配置代理类,否则配置目标类,这样增加系统功能很容易,以后运行一段时间后,邮箱去掉系统功能也很容易;

面向方面的编程AOP:系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面。如:安全,事务,日志贯穿到了好多个模块。

那么就是要使交叉业务模块化,可以采用将切面代码移动奥原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的,利用代理正好可以解决这种问题。代理是实现AOP功能的核心和关键技术

JVM可以在运行期间动态生成出类的字节码,这种动态生成的类万网被用作代理类,即动态代理类。

JVM生成的动态类必须实现一个或多个接口,所以,JVM的动态类只能用作具有相同接口的目标类的代理。CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,就用CGLIB库。

系统功能的位置:目标方法的前面后面,前后都有,异常块中

StringBuilder在单线程要效率高些,StringBuffer在多线程中使用

Collection proxy3=(Collection)Proxy.newProxyInstance();

Collection .class.getclassLoader();

new Class[](Collection.class,new InvocationHandler(){

});

构造方法接受一个InvocationHandler对象,要干什么呢?记住他,在其他的地方会用到。掉用代理的方法内部就会调用传递进来的InvocationHandler对象的invoke方法,方法中的三要素:

代理对象,方法,方法参数

代理对象返回结果就是目标返回的结果;

调用有返回值的方法时会有异常:它内部调用了invoke()方法,invoke返回一个null,返回值与invoke()方法的返回值不一样。

委托给Handler的方法有toString(),hashCode(),equals();

Java里怎样临时传递系统功能代码:

把系统功能封装成对象来编写可生成代理

实现AOP功能的封装与配置:

关键代码如下:Public class BeanFactory{

Properties props=new Properties();

Public BeanFactory(InputStream ips){

Props.load(ips);

}

}public Object getBean(String name){

String className==props.getProperty(name);//根据名字拿类名

Class clazzName=Class.forName(className);

Object bean=clazz.newInstance();

If(bean instanceof ProxyFactoryBean){

Object proxy=null;

ProxyFactoryBean proxyFactoryBean=( ProxyFactoryBean)bean;

Advice advice=(Advice)Class.forName(props.getProperty(name+”.advice”)).newInstance();//系统功能对象

Object target=class.forName(props.getProperty(name+”.advice”)).newInstance();

//目标对象

proxyFactoryBean.setAdvice(advice);

proxyFactory.setTarget(target);

Object proxy=ProxyFactoryBean(bean).getProxy();

}return null;

}

不管用不用代理都在文件里配,这就是spring框架,

希望在以后的学习中更加深入的学习框架,感觉框架的却很不错,就是有点繁琐了,多多进步吧

 ---------------------- android培训java培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net/heima