黑马程序员_类加载器、代理
2013-12-15 14:34
513 查看
------- android培训、java培训、期待与您交流!
----------
一、类加载器
1.实际上就是将.class文件加载进内存,也可以将普通类加载进内存。
2.Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader
BootStrap在Java JVM中用于加载别的类
ExtClassLoader在JRE/lib/ext/*.jar加载jar包
AppClassLoader用于加载ClassPath指定的所有jar或目录。
3.类加载器的委托机制:
每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异常。
自定义类加载器并实现加密解密:
代码如下:
要覆盖findClass方法,不用覆盖loadClass方法。原因是:为了保留原来的流程体系。
二、代理
概念:实际上就是要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能。
代理的作用:实际上就是在你的目标代码上,添加一些别的代码,你本身的代码也运行了。
这个新的代码就是代理。
代理类的好处:生成代理类后但你想要改变程序是不需要改变源程序。
交叉业务的编程问题即面向方面的编程(AOP),AOP的目标就是使交叉业务模块化,可以采用将切面代理移动到原始方法的周围,这与直接在方法中编写切面代理的过程效果是一样的。
实际上是面向一个面的,在一些目标方法的前后位置插入一些代码。
动态代理技术
概述:
1、要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,
这时就不能采用静态代理方式,需用动态代理技术。
注意:JVM生成的动态类必须实现一或多个接口,所以JVM生成的动态代理类只能用作具有相同接口的目标类代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以作为该类的代理,
所以,如果要为一个没有实现接口的类生成动态代理,那么可以使用CGLIB库
创建一个动态类:
Proxy:代理类
//得到一个类的class
Class clazz=
proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
这个代理类只有一个构造方法:
$proxy0(InvocationHandler i);
InvocationHandler是一个接口
//获取构造函数
Constructor constructor=clazz.getConstructor(InvocationHandler.class);
//创建动态类的实例对象方式一
//创建动态类的实例对象方式二
//获得对象
注意:不能调用有返回值的size方法,因为:size的返回int类型的,代码中是返回的null,null没有办法转变成int
//可以直接创建对象:
目标类中的方法怎么在代理类中执行的呢?
实际上目标类中的方法每被调用一次,就会执行一次invote方法。
InvocationHander的运行原理是:
下面是一个代理类的代码:
//代理类
利用动态代理模拟Spring框架
代码如下:
实际上模拟Spring框架,就是让类动态的切换代理类和普通类,也动态的可以加载配置问价中的内容,当你的需求想要改变时,只需该配置问件即可。
-------
android培训、java培训、期待与您交流! ----------
----------
一、类加载器
1.实际上就是将.class文件加载进内存,也可以将普通类加载进内存。
2.Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader
BootStrap在Java JVM中用于加载别的类
ExtClassLoader在JRE/lib/ext/*.jar加载jar包
AppClassLoader用于加载ClassPath指定的所有jar或目录。
3.类加载器的委托机制:
每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异常。
自定义类加载器并实现加密解密:
代码如下:
public class MyClassLoader extendsClassLoader{ public static void main(String[] args) throws Exception { String srcPath=args[0]; String desDir=args[1]; FileInputStream fileIn=new FileInputStream(srcPath); String desPath=desDir+"\\"+srcPath.substring(srcPath.lastIndexOf('\\')+1); FileOutputStream fileOut=new FileOutputStream(desPath); copyfile(fileIn,fileOut); fileIn.close(); fileOut.close(); } public static void copyfile(InputStream in,OutputStream out) throws Exception { int i=-1; while((i=in.read())!=-1) { out.write(i^0xff); } } private String desfiles; @Override protected Class findClass(String name) throws ClassNotFoundException { String file="javalib"+"//"+name+".class"; try { FileInputStream In=new FileInputStream(file); ByteArrayOutputStream by=new ByteArrayOutputStream(); copyfile(In,by); In.close(); byte[]bytes=by.toByteArray(); return defineClass(bytes,0,bytes.length); } catch(Exception e) { e.printStackTrace(); } return null; } public MyClassLoader() { } public MyClassLoader(String desfiles) { this.desfiles=desfiles; } } //测试类 public class ClassLoaderTest { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class calzz= new MyClassLoader("javalib").loadClass("ClassLoaderAttachment"); Date d=(Date) calzz.newInstance(); System.out.println(d); } }总结:自定义类加载器必须继承ClassLoader
要覆盖findClass方法,不用覆盖loadClass方法。原因是:为了保留原来的流程体系。
二、代理
概念:实际上就是要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能。
代理的作用:实际上就是在你的目标代码上,添加一些别的代码,你本身的代码也运行了。
这个新的代码就是代理。
代理类的好处:生成代理类后但你想要改变程序是不需要改变源程序。
交叉业务的编程问题即面向方面的编程(AOP),AOP的目标就是使交叉业务模块化,可以采用将切面代理移动到原始方法的周围,这与直接在方法中编写切面代理的过程效果是一样的。
实际上是面向一个面的,在一些目标方法的前后位置插入一些代码。
动态代理技术
概述:
1、要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,
这时就不能采用静态代理方式,需用动态代理技术。
注意:JVM生成的动态类必须实现一或多个接口,所以JVM生成的动态代理类只能用作具有相同接口的目标类代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以作为该类的代理,
所以,如果要为一个没有实现接口的类生成动态代理,那么可以使用CGLIB库
创建一个动态类:
Proxy:代理类
//得到一个类的class
Class clazz=
proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
这个代理类只有一个构造方法:
$proxy0(InvocationHandler i);
InvocationHandler是一个接口
//获取构造函数
Constructor constructor=clazz.getConstructor(InvocationHandler.class);
//创建动态类的实例对象方式一
class MyInvocationHander1 implements InvocationHandler{ public Objectinvoke(Object proxy, Method method, Object[] args) throws Throwable{ // TODOAuto-generated method stub return null; } }
//创建动态类的实例对象方式二
Collection proxy2 = (Collection)constructor.newInstance(newInvocationHandler(){ public Objectinvoke(Object proxy, Method method, Object[] args) throws Throwable{ return null; } });
//获得对象
Collection proxy1 =(Collection)constructor.newInstance(new MyInvocationHander1()); System.out.println(proxy1); proxy1.clear(); proxy1.size();
注意:不能调用有返回值的size方法,因为:size的返回int类型的,代码中是返回的null,null没有办法转变成int
//可以直接创建对象:
Object proxy3 = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), newInvocationHandler(){ publicObject invoke(Object proxy, Method method, Object[] args) throwsThrowable { }
目标类中的方法怎么在代理类中执行的呢?
实际上目标类中的方法每被调用一次,就会执行一次invote方法。
InvocationHander的运行原理是:
下面是一个代理类的代码:
//代理类
public class ProxyTest { public static void main(String[] args) throws Exception { ArrayList al=new ArrayList(); Collectionconllection = (Collection) getProxy(al,new MyAdvice()); conllection.add("aaaa"); conllection.add("bbbb"); conllection.add("cccc"); conllection.add("dddd"); System.out.println(conllection); } private static Object getProxy(final Objectobj,final Advice ad) { Collection conllection=(Collection)Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { ArrayList al=new ArrayList(); public Objectinvoke(Object proxy, Method method, Object[] args) throws Throwable { ad.beforeMethod(method); Object val=method.invoke(al, args); ad.afterMethod(method); return val; } }); returnconllection; } }
import java.lang.reflect.Method; public class MyAdvice implements Advice { long start; @Override public void afterMethod(Method method) { // TODO Auto-generated method stub long start=System.currentTimeMillis(); } @Override public void beforeMethod(Method method) { // TODO Auto-generated method stub longend=System.currentTimeMillis(); System.out.println(method.getName()+"yun xing de shijan"+(end-start)); } }
import java.lang.reflect.Method; public interface Advice { void beforeMethod(Method method); void afterMethod(Method method); }总结:实现一个代理,实际上就是在目标类的前后夹代码,上面代码把要加的方法抽出来了,抽成了一个MyAdvice类。这样可以随时改变要加入的方法。又抽成了Advice接口,有利于扩展性。
利用动态代理模拟Spring框架
代码如下:
import java.io.IOException; import java.io.InputStream; import java.util.Properties; importcn.itcast.day3.Advice; publicclass BeanFactory { Properties props = new Properties(); public BeanFactory(InputStream ips){ try { props.load(ips); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public Object getBean(String name){ String className =props.getProperty(name); Object bean = null; try { Class clazz = Class.forName(className); bean = clazz.newInstance(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if(bean instanceof ProxyFactoryBean){ Object proxy = null; ProxyFactoryBean proxyFactoryBean =(ProxyFactoryBean)bean; try { Advice advice =(Advice)Class.forName(props.getProperty(name +".advice")).newInstance(); Object target =Class.forName(props.getProperty(name + ".target")).newInstance(); proxyFactoryBean.setAdvice(advice); proxyFactoryBean.setTarget(target); proxy =proxyFactoryBean.getProxy(); } catch (Exception e) { // TODO Auto-generated catchblock e.printStackTrace(); } return proxy; } return bean; } }总结:这个代码主要是从配置文件中读取信息,并且判断返回的是代理对象,还是普通的对象。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import cn.itcast.day3.Advice; publicclass ProxyFactoryBean { private Advice advice; private Object target; public Advice getAdvice() { return advice; } public void setAdvice(Advice advice) { this.advice = advice; } public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public Object getProxy() { Object proxy3 = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler(){ public Object invoke(Objectproxy, Method method, Object[] args) throws Throwable { advice.beforeMethod(method); Object retVal =method.invoke(target, args); advice.afterMethod(method); return retVal; } } ); return proxy3; } }总结:这段代码是用于创建代理类。
import java.io.InputStream; import java.util.Collection; public class AopFrameworkTest { /** *@param args */ public static void main(String[] args)throws Exception { // TODO Auto-generated method stub InputStream ips =AopFrameworkTest.class.getResourceAsStream("config.properties"); Object bean = newBeanFactory(ips).getBean("xxx"); System.out.println(bean.getClass().getName()); ((Collection)bean).clear(); } }总结:这是用于进行测试的类。
实际上模拟Spring框架,就是让类动态的切换代理类和普通类,也动态的可以加载配置问价中的内容,当你的需求想要改变时,只需该配置问件即可。
-------
android培训、java培训、期待与您交流! ----------
相关文章推荐
- 黑马程序员-基础加强04类加载 动态代理
- 黑马程序员——内省,JavaBean,注解,泛型,类加载器,代理
- 黑马程序员-java高新技术-代理和类加载器
- 黑马程序员-基础加强04类加载 动态代理
- 【黑马程序员】技术加强之代理与动态加载类
- 黑马程序员_类加载器与动态代理
- 黑马程序员__类加载器__代理
- 黑马程序员_Java基础加强(下)_类加载器,代理_28
- 黑马程序员_java高新-类加载器及代理
- 黑马程序员_温习 高新技术二 (个人笔记)摘要(JavaBean类------注解------泛型------类加载器(代理))
- 黑马程序员 java高新技术<四>--类加载器、动态代理技术的深入讲解与应用
- 黑马程序员--Java基础加强--08内省、类加载器、动态代理
- 黑马程序员—Java提高3(注解,类加载器,代理)
- 黑马程序员-类加载器及动态代理
- 黑马程序员_类加载器、代理、AOP
- 黑马程序员---类加载与动态代理
- 黑马程序员_高新技术-内省、类加载器、代理
- 黑马程序员—(JAVA)类加载器、代理
- 黑马程序员--java高新技术 26--javaBean,泛型,类加载器,代理spring小框架
- 黑马程序员-java基础加强_代理和类加载器