什么是代理模式
为其他对象提供一种代理以控制对这个对象的访问
静态代理
模拟坦克的移动
public class Tank implements Movable {
/**
* 模拟坦克移动了一段儿时间
*/
@Override
public void move() {
System.out.println("Tank moving claclacla...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
interface Movable {
void move();
}
问题:我想记录坦克的移动时间
该怎么做呢
1.修改源码,不好
2.继承实现:如果还想记录日志,记录权限,就会多重继续,十分复杂
public class Tank implements Movable {
/**
* 模拟坦克移动了一段儿时间
*/
@Override
public void move() {
System.out.println("Tank moving claclacla...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Tank2().move();
}
}
class Tank2 extends Tank {
@Override
public void move() {
long start = System.currentTimeMillis();
super.move();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
interface Movable {
void move();
}
3.使用代理
public class Tank implements Movable {
/**
* 模拟坦克移动了一段儿时间
*/
@Override
public void move() {
System.out.println("Tank moving claclacla...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new TankTimeProxy(new Tank()).move();
}
}
class TankTimeProxy implements Movable {
Tank tank;
public TankTimeProxy(Tank tank) {
this.tank = tank;
}
@Override
public void move() {
long start = System.currentTimeMillis();
tank.move();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
interface Movable {
void move();
}
代理的嵌套
/**
* 问题:我想记录坦克的移动时间
* 最简单的办法:修改代码,记录时间
* 问题2:如果无法改变方法源码呢?
* 用继承?
* v05:使用代理
* v06:代理有各种类型
* 问题:如何实现代理的各种组合?继承?Decorator?
*/
public class Tank implements Movable {
/**
* 模拟坦克移动了一段儿时间
*/
@Override
public void move() {
System.out.println("Tank moving claclacla...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Tank tank=new Tank();
new TankLogProxy(
new TankTimeProxy(
new Tank()
)
).move();
}
}
class TankTimeProxy implements Movable {
Movable movable;
public TankTimeProxy(Movable movable) {
this.movable = movable;
}
@Override
public void move() {
long start = System.currentTimeMillis();
movable.move();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
class TankLogProxy implements Movable {
Movable movable;
public TankLogProxy(Movable movable) {
this.movable = movable;
}
@Override
public void move() {
System.out.println("start moving...");
movable.move();
System.out.println("stopped!");
}
}
interface Movable {
void move();
}
动态代理
静态代理一般都是预先定义好的,但如果我想在运行时段才指定代理哪个对象怎么办呢,这就是动态代理
package ProxyPatten;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Random;
public class Tank implements Movable {
/**
* 模拟坦克移动了一段儿时间
*/
@Override
public void move() {
System.out.println("Tank moving claclacla...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class LogHander implements InvocationHandler {
Tank tank;
public LogHander(Tank tank) {
this.tank = tank;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start moving");
Object o = method.invoke(tank, args);
System.out.println("stopped!");
return o;
}
public static void main(String[] args) {
Tank tank = new Tank();
Movable movable = (Movable)Proxy.newProxyInstance(
//类加载器
Tank.class.getClassLoader(),
//实现的接口
Tank.class.getInterfaces(),
//处理器
new LogHander(tank));
movable.move();
}
}
interface Movable {
void move();
}
Proxy.newInstance
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
Objects.requireNonNull(h);
final Class<?> caller = System.getSecurityManager() == null
? null
: Reflection.getCallerClass();
/*
* Look up or generate the designated proxy class and its constructor.
* 寻找或者生成代理类的构造者
*/
Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
return newProxyInstance(caller, cons, h);
}
private static Constructor<?> getProxyConstructor(Class<?> caller,
ClassLoader loader,
Class<?>... interfaces)
{
// optimization for single interface
if (interfaces.length == 1) {
Class<?> intf = interfaces[0];
if (caller != null) {
checkProxyAccess(caller, loader, intf);
}
return proxyCache.sub(intf).computeIfAbsent(
loader,
(ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
);
} else {
// interfaces cloned
final Class<?>[] intfsArray = interfaces.clone();
//检测权限
if (caller != null) {
checkProxyAccess(caller, loader, intfsArray);
}
final List<Class<?>> intfs = Arrays.asList(intfsArray);
//proxy有一个缓存,在缓存里查找,如果没有生成新的
return proxyCache.sub(intfs).computeIfAbsent(
loader,
(ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
);
}
}
生成的proxy类
在main函数加上
System.getProperties().put(“jdk.proxy.ProxyGenerator.saveGeneratedFiles”,“true”);即可生成
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.mashibing.dp.proxy.v10;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
final class $Proxy0 extends Proxy implements Movable {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
//传入handler
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void move() throws {
try {
//执行的handler的invoke方法
//this 是指当前Proxy对象,m3move方法
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
//根据反射获取的方法,m3既是move方法
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.mashibing.dp.proxy.v10.Movable").getMethod("move");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
cglib实现动态代理
CGLIB实现动态代理不需要接口
public class Main {
public static void main(String[] args) {
//enhancer 代理
Enhancer enhancer = new Enhancer();
//代理的类
enhancer.setSuperclass(Tank.class);
//处理方式
enhancer.setCallback(new TimeMethodInterceptor());
//生成
Tank tank = (Tank)enhancer.create();
tank.move();
}
}
class TimeMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(o.getClass().getSuperclass().getName());
System.out.println("before");
Object result = null;
result = methodProxy.invokeSuper(o, objects);
System.out.println("after");
return result;
}
}
class Tank {
public void move() {
System.out.println("Tank moving claclacla...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4. AOP
在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。