类加载器
类加载器作用:将加载进入内存
使用:对象.getClass().getClassLoader()
加载类型:
- 引导类:JDK的核心类库(String,Object等)
- 系统类:自己写的类
- 扩展类:JDK的扩展类(lib/ext下的类)
静态代理
使用装饰者设计模式
pl:IO流中的缓冲流:BufferedRead必须依赖原有的IO对象,new BufferedReader(new FileReader)
实现装饰模式
- 原有对象和装饰对象必须拥有相同的父类,或者相同的接口
- 使用装饰对象必须将原有对象传递过来
- 重写原来的方法,增强功能
动态代理
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
参数:
- loader - 被代理对象的类加载器
- interfaces - 被代理对象实现的所有接口
- h - 被创建出来的代理对象要做的事情
返回:
一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
//InvocationHandler接口的方法
Object invoke(Object proxy,
Method method,
Object[] args)
throws Throwable
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
参数:
- proxy - 在其上调用方法的代理实例(被创建好的代理对象)
- method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。(被代理对象执行的方法)
- args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。(被代理对象执行方法需要的参数)
例子
package com.ahu.proxyTest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
* 实现动态代理
* 被代理对象:ArrayList
* 被代理方法:拒绝修改长度的方法如:add,addAll,remove
*
* 使用Proxy类创建一个代理对象
*/
public class proxyTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("jack");
list.add("rose");
//传递一个被代理对象,返回代理对象
list = proxy(list);
// list.add("abc");//以下使用的是代理方法invoke
int size = list.size();
System.out.println(size);
System.out.println(list.get(0));
}
/**
*
* @param list 想要代理的对象
*/
public static List<String> proxy(List<String> list){
//工具类创建代理对象
return (List<String>) Proxy.newProxyInstance(list.getClass().getClassLoader(), list.getClass().getInterfaces()
, new InvocationHandler() {
/**
* 属于代理对象的方法,类比经纪人
* 只要使用了被代理对象的方法,并不会直接执行list的方法,而是执行invoke方法
* @param proxy 代理人对象
* @param method 被代理对象执行的方法
* @param args 方法的实际参数
* @return 被代理对象调用方法的返回值,list.size()返回int
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("add")){
throw new RuntimeException("add禁止调用");
}
if(method.getName().equals("remove")){
throw new RuntimeException("remove禁止调用");
}
//其他方法可以调用
return method.invoke(list, args);
}
});
}
}