概念:
代理模式:为其他对象提供一种代理,以控制对这个对象的访问。
在代理模式中又分为两种:静态代理和动态代理。代理模式一般默认指静态代理模式。
静态代理模式:该类型有具体的实现,即就是存在该类型的class文件。
动态代理模式:及就是只有接口规范,没有具体的实现。也不存在class文件。
实现:
静态代理:
定义代理对象接口:
public interface Author { /** * 作家具有写作的能力 */ void write(); }
代理对象实现类
public class NovelAuthor implements Author {
@Override
public void write() {
System.out.println("我是一个写小说的,现在要准备写小说了");
}
}
代理类实现
public class ProxyNovelAuthor implements Author {
private NovelAuthor author;
public ProxyNovelAuthor() {
author = new NovelAuthor();
}
@Override
public void write() {
System.out.println("每次写作之前我都要喝杯咖啡,我刚喝完咖啡");
author.write();
System.out.println("写作完成了,签上我的名字送给你。");
}
}
动态代理:
代理类接口:
public interface Author { /** * 作家具有写作的能力 */ void write(); }
代理类Handler,实现InvocationHandler
public class AuthorInvocationHandler implements InvocationHandler { private Object obj; public AuthorInvocationHandler(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我写作之前,都要喝咖啡。"); Object result = method.invoke(this.obj, args); System.out.println("我写完了,签名并送给你。"); return result; } }
测试实现及结果:
实现:
@Test public void proxyTest() { ProxyAuthor proxyAuthor = new ProxyAuthor(novelAuthor); proxyAuthor.write(); } @Test public void dynamicProxyTest_1() { AuthorInvocationHandler authorInvocationHandler = new AuthorInvocationHandler((Author) () -> System.out.println("我是现在要准备写小说了")); ClassLoader classLoader = authorInvocationHandler.getClass().getClassLoader(); Class[] cls = new Class[]{Author.class}; Author author = (Author) Proxy.newProxyInstance(classLoader, cls, authorInvocationHandler); author.write(); } @Test public void dynamicProxyTest_2() { AuthorInvocationHandler authorInvocationHandler = new AuthorInvocationHandler((Author) () -> System.out.println("我是现在要准备写一本工具书...")); ClassLoader classLoader = authorInvocationHandler.getClass().getClassLoader(); Class[] cls = new Class[]{Author.class}; Author author = (Author) Proxy.newProxyInstance(classLoader, cls, authorInvocationHandler); author.write(); }
静态代理结果:
每次写作之前我都要喝杯咖啡,我刚喝完咖啡
我是一个写小说的,现在要准备写小说了
写作完成了,签上我的名字送给你。
动态代理结果1:
我写作之前,都要喝咖啡。
我是现在要准备写小说了
我写完了,签名并送给你。
动态代理结果2:
我写作之前,都要喝咖啡。
我是现在要准备写一本工具书...
我写完了,签名并送给你。
分析:
1.静态代理和动态代理的区别:静态代理必须有代理对象的实现类,动态代理则不需要,有也没关系。静态代理类一般和被代理对象类实现同一个代理对象类接口,目的是为了保证有相同的行为。动态代理对象在使用Proxy静态方法是必须要求传入一个接口类型,所以动态代理接口是必须的。其他的区别都不是核心区别。
2.都方便扩展,但静态代理没有动态代理方便扩展,但目的都是为了解耦合。
3.静态代理相当于我们利用重写的方式覆盖了原本的方法,动态代理,是利用反射机制实现的调用方法时,添加一些前后操作。
4.无论是静态代理还是动态代理,对于代理对象来说,都不能直接访问被代理对象的属性,也就是他们只代理了行为,属性并不会被他们代理。
5.动态代理在没有具体实现类的情况下,没有属性引用,当然动态代理也可以对代理对象进行具体的实现,这样就能用到里面的属性了。
6.能在不改变原有对象行为的前提下,对原有行为进行适当的改变。
7.适用场景:远程代理、智能引用代理、保护代理、缓存代理、同步代理、虚拟代理
a.RMI远程调用
b.AOP实现也使用了
...
经典框架中使用的:
Spring中大量使用,hibernate、mybatis数据库连接池中使用,以及事务控制的也有使用