本帖最后由 小江哥 于 2018-8-3 20:38 编辑
概述代理模式为另一个对象提供一个替身或者占位符以控制对这个对象的访问 如下图所示 UML类图代理模式类别代码实现静态代理
[Java] 纯文本查看 复制代码 public interface Subject {
void request();
}
// 请求的真实目标对象
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("real subject execute request");
}
}
// 代理对象
public class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
System.out.println("before");
try {
realSubject.request();
} catch (Exception e) {
System.out.println("ex:" + e);
throw e;
} finally {
System.out.println("after");
}
}
}
[Java] 纯文本查看 复制代码 public class Client {
public static void main(String[] args) throws Exception {
Subject subject = new Proxy(new RealSubject());
subject.request();
}
}
[Java] 纯文本查看 复制代码 before
real subject execute request
after
- 静态代理有一个很明显的缺点:代理的方法越多,重复代码越多。
- 就不符合DRY原则。于是 就产生了动态代理
动态代理
jdk代理
- JDK 为我们提供了一种动态代理的实现,通过实现 InvocationHandler 接口来实现动态代理。
- 代理类代码
[Java] 纯文本查看 复制代码 public class JdkProxySubject implements InvocationHandler {
private RealSubject realSubject;
public JdkProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = null;
try {
result = method.invoke(realSubject, args);
} catch (Exception e) {
System.out.println("ex" + e);
throw e;
} finally {
System.out.println("after");
}
return result;
}
}
[Java] 纯文本查看 复制代码 public class Client {
public static void main(String[] args) throws Exception {
Subject subject = (Subject) Proxy.newProxyInstance(Client.class
.getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
subject.request();
}
}
[Java] 纯文本查看 复制代码 before
real subject execute request
after
- 上面讲了动态代理是解决代码重复的问题。我们来验证下
- 首先,在Subject 接口中增加一个hello方法
[Java] 纯文本查看 复制代码 public interface Subject {
void request();
void hello();
}
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("real subject execute request");
}
@Override
public void hello() {
System.out.println("real subject execute hello");
}
}
- 静态代理类 如果想要代理hello 这个方法。就要在代理类中实现这个方法
[Java] 纯文本查看 复制代码 public class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void hello() {
...
}
}
[Java] 纯文本查看 复制代码 public class Client {
public static void main(String[] args) throws Exception {
Subject subject = (Subject) Proxy.newProxyInstance(Client.class
.getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
subject.hello();
}
}
[Java] 纯文本查看 复制代码 before
real subject execute hello
after
Cglib代理[Java] 纯文本查看 复制代码 public class DemoMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before in cglib");
Object result = null;
try {
result = proxy.invokeSuper(object,args);
}catch (Exception e){
System.out.println("get ex :" + e.getMessage());
throw e;
}finally {
System.out.println("after in cglib");
}
return result;
}
}
[Java] 纯文本查看 复制代码 public class Client {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new DemoMethodInterceptor());
Subject subject = (Subject) enhancer.create();
subject.request();
}
}
[Java] 纯文本查看 复制代码 before in cglib
real subject execute request
after in cglib
JDK代理和Cglib代理区别- JDK代理只能针对有接口的类的方法进行代理
- Cglib基于继承来实现代理,无法对static、final 类进行代理
- Cglib基于继承来实现代理,无法对private、static 方法 进行代理
|