Java 代理学习笔记
java代理
特征: 代理类和委托类有同样的接口, 代理类主要为委托类预处理消息, 过滤消息, 吧消息转发给委托类, 以及处理事后消息, 代理类的对象并不真正实现服务, 而是通过调用委托类的相关方法, 来提供特定的服务.
简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性, 因为这种间接性我们可以附加多种用途.
代理模式
- 代理模式: 为其他对象为提供一种代理以控制对这个对象的访问.
classDiagram
class Super{
<<interface>>
+operation()
}
class SubObject{
+operation()
}
Super <|.. SubObject : 实现
class Proxy{
+operation()
}
Super <|.. Proxy : 实现
SubObject <-- Proxy : 控制权
Super类定义了SubObject和Proxy的公用接口, 这样在需要使用SubObject的任何地方都可以使用Proxy.
应用场景:
- 远程代理: 远程对象的本地代表, 本地方法调用这个对象会被转发到远程中.
- 虚拟代理: 虚拟化开销大的对象
- 安全代理: 控制访问权限
- 智能指引: 调用真实的对象时, 处理另外一些事
静态代理
在编译时期就已经将接口, 被代理类等确定下来. 在程序运行之前代理类的.class文件就已经生成.
例子:
classDiagram
class Interface{
<<interface>>
void doSomthing()
void doSomthingElse()
}
class InterfaceImplFirst{
void doSomthing()
void doSomthingElse()
}
class InterfaceImplTwo{
void doSomthing()
void doSomthingElse()
}
Interface <|.. InterfaceImplFirst : 实现
Interface <|.. InterfaceImplTwo : 实现
InterfaceImplFirst <-- InterfaceImplTwo : 代理
Interface.class
public interface Interface {
void doSomething();
void doSomethingElse(String arg);
}
InterfaceImplFirst.class
public class InterfaceImplFirst implements Interface{
public void doSomething() {
System.out.println("InterfaceImplFirst: doSomething");
}
public void doSomethingElse(String arg) {
System.out.println("InterfaceImplFirst: doSomethingElse " + arg);
}
}
InterfaceImplTwo.class
public class InterfaceImplTwo implements Interface {
private final Interface interfaceImplFirst;
public InterfaceImplTwo(Interface interfaceImplFirst){
this.interfaceImplFirst = interfaceImplFirst;
}
public void doSomething() {
interfaceImplFirst.doSomething();
System.out.println("InterfaceImplTwo: doSomething");
}
public void doSomethingElse(String arg) {
interfaceImplFirst.doSomethingElse(arg);
System.out.println("doSomethingElse: doSomethingElse " + arg);
}
}
反射
基本使用:
//获取Class对象的三种方法:
Class<User> clazz = User.class;
Class<User> clazz = user.getClass();
Class<User> clazz = Class.forName(User.class);
//Class获取属性
public Field getField(String name) {...} //获取指定名称字段
public Method getMethod(String name, Class<?>... parameterTypes) {...} //获取指定名称和签名的方法
public Constructor<T> getConstructor(Class<?>... parameterTypes){...} //获取指定参数列表公有构造器
public Constructor<?>[] getConstructors() throws SecurityException {...} //获取所有公有构造器
//记载和类位于同一目录下的资源, 通过类加载器获取
public java.net.URL getResource(String name) {...} //返回URL形式的资源
public InputStream getResourceAsStream(String name) {...} //返回输入流形式的资源
//Constructor构造器的操作
public void setAccessible(boolean flag) {...} //给予私有化构造方法,成员方法,成员变量操作权限
public T newInstance(Object ... initargs) {...} //通过这个构造器声明一个类的新实例
public int getModifiers() {...} //获取构造器的访问修饰符
//Method方法调用
public Object invoke(Object obj, Object... args) {...} //obj为操作对象静态方法为null, args为方法参数
详情可以参考博客
例子:
Class<?> clazz = Class.forName("java.util.Date");
Date instance = (Date)clazz.newInstance();
使用反射复制数组:
使用Object类实现:
public static Object copy(Object array, int newLength){
Objects.requireNonNull(array);
Class<?> clazz = array.getClass();
System.out.println(clazz.getName());
if (!clazz.isArray()) {
return null;
}
Class<?> componentType = clazz.getComponentType();
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(array, 0, newArray, 0, newLength);
return newArray;
}
泛型方式实现:
public static <T> T copy(T array, int newLength){
Objects.requireNonNull(array);
Class<?> clazz = array.getClass();
if (!clazz.isArray()){
return null;
}
Class<?> componentType = clazz.getComponentType();
Object o = Array.newInstance(componentType, newLength);
System.arraycopy(array, 0, o, 0, newLength);
return (T)o;
}
使用泛型和反射实现模型转换:
public class Converter {
public static <T, S> T convert(S s, Class<T> clazz){
try {
T t = clazz.newInstance();
if (s == null){
return t;
}
BeanUtils.copyProperties(s, t);
return t;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
动态代理
在程序执行中创建对象, 不需要程序员去创建文件
功能:
- 控制访问, 在代理中控制是否可以调用目标的方法
- 功能增强, 在完成目标调用时, 附加额外的一些功能, 这些额外的功能叫做功能增强
优点:
-
不用创建代理类
-
可以给不同的目标随时创建代理
流程:
JDK实现动态代理:
- 创建一个处理程序, 经过这个处理程序处理的类的方法执行都会将耗时打印在控制台上
class MyInvokeHandler<T> implements InvocationHandler {
private T proxied = null;
public MyInvokeHandler(T proxied){
this.proxied = proxied;
}
/**
*
* @param proxy
* @param method 代理对象的动作
* @param args 动作的参数列表
* @return 返回
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long before = System.currentTimeMillis();
Object invoke = method.invoke(proxied, args); //使用反射调用类中的方法
long after = System.currentTimeMillis();
System.out.println(method.getName() + " used time: " + (after - before));
return invoke;
}
}
- 下面是被代理对象和其实现接口
interface Super{
void printHello(String param);
}
class Proxied implements Super{
public void printHello(String param){
System.out.println("Hello Proxied: " + param);
}
}
- 实现动态代理
//1. 创建一个被代理类, 就是被处理程序处理的类
Proxied proxied = new Proxied();
//2. 创建程序处理类处理这个被代理类
InvocationHandler handler = new MyInvokeHandler<>(proxied);
//3. 根据程序处理类动态生成代理类
Class<?> proxyClass = Proxy.getProxyClass(Super.class.getClassLoader(), Super.class);
//4. 生成代理类的构造器
Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
//5. 使用代理类的构造器生成代理对象
Super s = (Super)constructor.newInstance(handler);
//6. 检测代理是否有效
s.printHello("axianibiru");
或者:
//1. 创建被代理类
Proxied proxied = new Proxied();
//2. 生成代理处理程序
InvocationHandler handler = new MyInvokeHandler<Super>(proxied);
//3. 根据代理处理程序动态生成代理类
Super s = (Super)Proxy.newProxyInstance(Super.class.getClassLoader(), new Class<?>[]{Super.class}, handler);
//4. 调用被代理后的方法
s.printHello("axianibiru");
//5. 查看代理类行信息
Class<? extends Super> clazz = s.getClass();
//6. 查看继承和实现关系
Class<?> superclass = clazz.getSuperclass();
System.out.print(clazz.getName() + " extends " + superclass);
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.print( " implements " + anInterface.getName() + " ");
}
输出:
Hello Proxied: axianibiru
printHello used time: 0
com.proxyTest.dynamicProxy.thridDemo.$Proxy0 extends class java.lang.reflect.Proxy implements com.proxyTest.dynamicProxy.thridDemo.Super

浙公网安备 33010602011771号