六大设计原则
- 单一职责(一个类干一件事)
- 接口原则(接口方法都能用到)
- 依赖倒转(接口编程) --用到
- 里氏替换(继承性的重写改变了,复用性差)
- 开闭原则(扩展开放、修改关闭) --用到
- 迪米特法则(一个类对其他类保持最少的了解) --用到
代理模式是什么
代理模式:为其它对象提供一种代理以控制对这个对象的访问控制;在某些情况下,客户不想或者不能直接引用另一个对象,这时候代理对象可以在客户端和目标对象之间起到中介的作用
应用场景
统计每个 api 的请求耗时
统一的日志输出
校验被调用的 api 是否已经登录和权限鉴定
Spring的 AOP 功能模块就是采用动态代理的机制来实现切面编程
静态代理
优点:解耦(客户端不知道具体的实现是什么,只需注重业务代码是实现)
缺点:静态代理方式需要为每个接口实现一个代理类,而这些代理类中的代码
几乎是一致的。这在大型系统中将会产生很大的维护问题。
抽象主题类
public interface Subject {
/**
* 接口方法
*/
public void SMethod();
}
具体实现类
public class SmallSubject implements Subject {
@Override
public void SMethod() {
//业务处理逻辑
}
}
代理类(每个代理对象都需一个代理类实现代理)
public class Proxy implements Subject {
/**
* 要代理的实现类
*/
private Subject subject = null;
/**
* 默认代理自己
*/
public Proxy() {
this.subject = new Proxy();
}
public Proxy(Subject subject) {
this.subject = subject;
}
/**
* 构造函数,传递委托者
*
* @param objects 委托者
*/
public Proxy(Object... objects) {
}
/**
* 实现接口方法 可以增强方法
*/
@Override
public void SMethod() {
this.before();
this.subject.SMethod();
this.after();
}
/**
* 预处理
*/
private void before() {
//do something
}
/**
* 后处理
*/
private void after() {
//do something
}
}
客户端类
public class Client {
public static void main(String[] args) {
Subject subject = new SmallSubject();
Proxy proxy = new Proxy(subject);
proxy.SMethod();
}
}
动态代理(在运行时,创建目标类,可以调用和扩展目标类的方法)
JDK动态代理
所谓的jdk代理指的是借助jdk所提供的相关类来实现代理模式,其主要有两个类:InvocationHandler和Proxy。在实现代理模式时,只需要实现InvocationHandler接口即可,
要实现动态代理的首要条件:被代理类必须实现一个接口,才能被代理
优点:动态代理的应用使我们的类职责更加单一,复用性更强。代理逻辑与业务逻辑是互相独立的,没有耦合
JDK代理对象
public class JdkProxy implements InvocationHandler {
/**
* 目标对象
*/
private Object target;
/**
* 绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。
*
* @param target 绑定具体的代理实例
*/
public JdkProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
return result;
}
}
客户端
public class ProxyClient {
public static void main(String[] args) {
UserInterface user = new OverUser();
JdkProxy jdkProxy = new JdkProxy(user);
OverUser proxyUser = (OverUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), jdkProxy);
proxyUser.getName();
}
}
Cglib动态代理
Cglib代理是功能最为强大的一种代理方式,因为其不仅解决了静态代理需要创建多个代理类的问题,还解决了jdk代理需要被代理对象实现某个接口的问题。
public class CglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = methodProxy.invokeSuper(o, objects);
return result;
}
}
客户端
public class Test {
public static void main(String[] args) {
OverUser user = new OverUser();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OverUser.class);
enhancer.setCallback(intermediary);
OverUser rentProxy = (OverUser) enhancer.create();
rentProxy.getName();
}
}