--------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------
类加载器:
类加载器就是加载类的工具。
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap,
ExtClassLoader,
AppClassLoader 。
类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不
是java类,就是BootStrap。
类加载器的委托机制:
加载过程:
1、首先当前线程的类加载器去加载线程中的第一个类。
2、如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
3、还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
4、每个类加载器加载类时,又先委托给其上级类加载器。
自定义一个类加载器:
Java代码
- 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、将创建动态类的实例对象的代理改成匿名内部类的形式编写,锻炼大家习惯匿名内部类。
动态代理的原理图:
编写代理类:
通过反射得到构造方法,创建代理对象:
Java代码
- 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;
- }
- });
由代理直接创建代理对象:
Java代码
- 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代码:
Java代码
- 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代码:
Java代码
- 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代码:
Java代码
- 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();
- }
- }
--------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------