------- android培训、java培训、期待与您交流! ----------
类加载器:
类加载器就是加载类的工具。
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap,
ExtClassLoader,
AppClassLoader 。
类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不
是java类,就是BootStrap。
类加载器的委托机制:
加载过程:
1、首先当前线程的类加载器去加载线程中的第一个类。
2、如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
3、还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
4、每个类加载器加载类时,又先委托给其上级类加载器。
自定义一个类加载器:
public class MyClassLoader extends ClassLoader { public static void main(String[] args) throws Exception { String srcPath = args[0]; String destDir = args[1]; FileInputStream fis = new FileInputStream(srcPath); String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);//目标文件名 String destPath = destDir + "\\" + destFileName;//目标路径 FileOutputStream fos = new FileOutputStream(destPath); cypher(fis,fos);//加密导出 fis.close(); fos.close(); } //加密方法 private static void cypher(InputStream ips, OutputStream ops) throws Exception { int b = -1; while((b=ips.read()) != -1) { ops.write(b ^ 0xff); } } private String classDir; //重写findClass方法 @Override protected Class<?> findClass(String name) throws ClassNotFoundException { String classFileName = classDir + "\\" + name + ".class"; FileInputStream fis = null; try { fis = new FileInputStream(classFileName); ByteArrayOutputStream bos = new ByteArrayOutputStream(); cypher(fis,bos); fis.close(); byte[] bytes = bos.toByteArray(); return defineClass(bytes,0,bytes.length); } catch (Exception e) { e.printStackTrace(); } return super.findClass(name); } public MyClassLoader() { } public MyClassLoader(String classDir) { this.classDir = classDir; } }
-----------------------------------------------------------------------------------------
动态代理:
AOP(面向切面编程):
系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,如下所示:
安全 事务 日志
StudentService ------|----------|------------|-------------
CourseService ------|----------|------------|-------------
MiscService ------|----------|------------|-------------
用具体的程序代码描述交叉业务:
method1 method2 method3
{ { {
------------------------------------------------------切面
.... .... ......
------------------------------------------------------切面
} } }
交叉业务的编程问题即为面向方面的编程(Aspect oriented program ,简称AOP),AOP的目标就是要使交叉业
务模块化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样
的,如下所示:
------------------------------------------------------切面
func1 func2 func3
{ { {
.... .... ......
} } }
------------------------------------------------------切面
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现
接口的类生成动态代理类,那么可以使用CGLIB库。
创建动态类的实例对象过程:
1、用反射获得构造方法
2、编写一个最简单的InvocationHandler类
3、调用构造方法创建动态类的实例对象,并将编写的InvocationHandler类的实例对象传进去
4、打印创建的对象和调用对象的没有返回值的方法和getClass方法,演示调用其他有返回值的方法报告了
异常。
5、将创建动态类的实例对象的代理改成匿名内部类的形式编写,锻炼大家习惯匿名内部类。
动态代理的原理图:
编写代理类:
通过反射得到构造方法,创建代理对象:
Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class); Collection proxy1 = (Collection) constructor.newInstance(new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } });
由代理直接创建代理对象:
Collection proxy2 = (Collection)Proxy.newProxyInstance( Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler(){ ArrayList target = new ArrayList(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object retVal = method.invoke(target, args); return retVal; } } );
AOP简单框架的实现:
工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据
参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,
则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。
ProxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供目标(target)、通告(advice)。
ProxyFactoryBean代码:
public class 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 proxy = Proxy.newProxyInstance(//由代理类直接创建代理对象 target.getClass().getClassLoader(),//目标对象的类加载器 target.getClass().getInterfaces(),//目标对象实现的接口 new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { advice.beforeMethod(method);//方法前advice Object retVal = method.invoke(target, args);//调用目标要调用的方法 advice.afterMethod(method);//方法后advice return retVal; } } ); return proxy; } }
BeanFactory代码:
public class BeanFactory { Properties props = new Properties(); //使用构造方法导入资源配置文件 public BeanFactory(InputStream ips) { try { props.load(ips); } catch (IOException e) { e.printStackTrace(); } } //获得bean方法 public Object getBean(String name) { String className = props.getProperty(name); Class clazz = null; Object bean = null; try { clazz = Class.forName(className);//加载这个类 bean = clazz.newInstance();//创建该类的对象 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if(bean instanceof ProxyFactoryBean) {//判断这个类是不是代理 Object proxy = null; try { ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean;//拿到一个代理bean工厂 //创建advice 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) { e.printStackTrace(); } return proxy; } return bean; } }
MyAdvice代码:
public class MyAdvice implements Advice { private long beginTime = 0; @Override public void afterMethod(Method method) { long endTime = System.currentTimeMillis(); System.out.println(method.getName() + " running time of " + (endTime - beginTime)); } @Override public void beforeMethod(Method method) { beginTime = System.currentTimeMillis(); } }
相关推荐
黑马程序员_毕向东_Java基础视频教程第18天-14-IO流(拷贝文本文件图例).zip
黑马程序员_Java基础辅导班教程课件[第01期]第15天
黑马程序员_Java基础辅导班教程课件[第01期]第12天
黑马程序员_Java基础辅导班教程课件[第01期]第8天
黑马程序员_Java基础辅导班教程课件[第01期]第12天
黑马程序员_Java基础辅导班教程课件[第01期]第11天
黑马程序员_hibernate框架开发2016版讲义和笔记资料_day02
黑马程序员_Java基础辅导班教程课件[第01期]第7天
黑马程序员_Java基础辅导班教程课件[第01期]第5天
黑马程序员_hibernate框架开发2016版讲义和笔记资料_day1_day2_day3_day4 包含4天的教学文档
黑马程序员_张孝祥_Java多线程与并发库,视频+代码+资料
黑马程序员_Java基础辅导班教程课件[第01期]第12天
黑马程序员_Java基础辅导班教程课件[第01期]第6天
黑马程序员_Java基础辅导班教程课件[第01期]第4天
黑马程序员_Java基础辅导班教程课件[第01期]第10天
黑马程序员_Java基础辅导班教程课件[第01期]第9天
( 01_黑马程序员_张孝祥_Java基础加强_课程价值与目标介绍.zip )
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
黑马程序员_毕向东_Java基础视频教程第22天-06-GUI(Action事件).zip
黑马程序员_毕向东_Java基础视频教程第18天-09-IO流(文件的续写)