代理模式
Provide a surrogate or placeholder for another object to control access to it.
为其他对象提供一个代理或占位符来控制对它的访问。
静态代理
public class StaticProxy {
@Test
public void all() {
final Runner runner = new Runner();
final RunProxy runProxy = RunProxy.builder().runner(runner).build();
// 通过代理角色实现对真实角色的访问控制
runProxy.run();
}
}
/**
* 1)需要执行代理的行为
*/
interface IRun {
void run();
}
/**
* 2)实现行为的真实角色
*/
@Slf4j
class Runner implements IRun {
@Override
public void run() {
log.info("真实角色的行为");
}
}
/**
* 3)持有真实角色的代理角色,可控制外部对代理的访问
*/
@Builder
@Slf4j
class RunProxy implements IRun {
private final IRun runner;
@Override
public void run() {
if (ThreadLocalRandom.current().nextBoolean()) {
// 执行真实角色的行为
runner.run();
} else {
log.error("代理心情不好,拒绝处理");
}
}
}
动态代理
public class DynamicProxy {
/**
* 代理模式:
* Provide a surrogate or placeholder for another object to control access to it.
* 为其他对象提供一个代理或占位符来控制对它的访问。
*/
@Test
public void all() {
final TargetImpl targetImpl = new TargetImpl();
final LogAdvice logAdvice = new LogAdvice();
final SelfProxy selfProxy = SelfProxy.builder()
.target(targetImpl)
.advice(logAdvice).build();
final Itarget target = (Itarget) selfProxy.proxy();
target.show();
}
}
/**
* 1)需要执行动态代理的目标接口
*/
interface Itarget {
void show();
}
/**
* 2)目标接口的实现类
*/
@Slf4j
class TargetImpl implements Itarget {
@Override
public void show() {
log.info("调用目标方法");
throw new RuntimeException("测试异常");
}
}
/**
* 3)动态织入的通知接口
*/
interface Iadvice {
// 前置通知
void before();
// 后置通知
void after();
// 环绕通知
Object around(Object target, Method method, Object[] args);
// 返回通知
void afterReturning();
// 异常通知
void afterThrowing();
}
/**
* 通知接口的抽象实现,以简化实现通知接口所需要的工作。
*/
@Slf4j
abstract class BaseAdvice implements Iadvice {
@Override
public void before() {
}
@Override
public void after() {
}
@Override
public Object around(Object target, Method method, Object[] args) {
try {
log.info("执行环绕方法", "around");
return method.invoke(target, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
@Override
public void afterReturning() {
}
@Override
public void afterThrowing() {
}
}
/**
* 4)具体的通知实现类
*/
@Slf4j
class LogAdvice extends BaseAdvice {
private final ThreadLocal<Long> startTime = new ThreadLocal();
@Override
public void before() {
log.info("开始执行方法 {}", "before");
startTime.set(System.nanoTime());
}
@Override
public void after() {
final Long start = startTime.get();
final long executeTime = System.nanoTime() - start;
log.info("方法执行完毕 {}", "after");
log.info("方法执行时间 {}", executeTime);
}
@Override
public Object around(Object target, Method method, Object[] args) {
try {
log.info("执行环绕方法 {}", "around");
return method.invoke(target, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
@Override
public void afterReturning() {
log.info("方法返回 {}", "afterReturning");
}
@Override
public void afterThrowing() {
log.info("方法抛出异常 {}", "afterThrowing");
}
}
/**
* 5)动态代理类
*/
@Builder
@AllArgsConstructor
class SelfProxy implements InvocationHandler {
// 要代理的目标对象
private final Object target;
// 动态织入的通知接口
private final Iadvice advice;
@Override
public Object invoke(Object target, Method method, Object[] args) throws Throwable {
// 执行前置通知
advice.before();
try {
// 执行环绕通知,此处方法的主体一定要是被代理对象。
final Object around = advice.around(this.target, method, args);
// 执行后置通知
advice.after();
return around;
} catch (final Exception e) {
// 执行异常通知
advice.afterThrowing();
throw new IllegalStateException(e);
} finally {
// 执行返回通知
advice.afterReturning();
}
}
public Object proxy() {
// 获取指定接口的动态代理类,基于 JDK 的 Proxy 实现。
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}