Java基础加强——动态代理
Posted ---江北
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础加强——动态代理相关的知识,希望对你有一定的参考价值。
代理模式:
为其他对象提供一种代理以控制对这个对象的访问。
代理模式主要分为两类:
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成
1.静态代理相对好理解一些,来看下面的代码:
接口 Count.java
/**
* 账户接口
* @author jiangbei01
*
*/
public interface Count {
void add();
void update();
}
实现类 CountImpl
package cn.test;
public class CountImpl implements Count {
@Override
public void add() {
System.out.println("真实对象.add");
}
@Override
public void update() {
System.out.println("真实对象.update");
}
}
代理对象CountProxy.java
package cn.test;
public class CountProxy implements Count {
//持有真实对象引用
private CountImpl countImpl;
//覆盖默认构造器
public CountProxy(CountImpl countImpl) {
super();
this.countImpl = countImpl;
}
@Override
public void add() {
System.out.println("代理对象执行add前");
countImpl.add();
System.out.println("代理对象执行add后");
}
@Override
public void update() {
System.out.println("代理对象执行update前");
countImpl.update();
System.out.println("代理对象执行update后");
}
}
看看测试代码:
public class Test01 {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.add();
System.out.println("===========================");
countProxy.update();
}
}
运行结果也容易得出:
代理对象执行add前
真实对象.add
代理对象执行add后
===========================
代理对象执行update前
真实对象.update
代理对象执行update后
容易看出静态代理缺点:每个代理只能为一个接口服务,并且重复代码量大!
2.动态代理:java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
Proxy类提供的方法:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
其中最后一个参数 InvocationHandler h 得到InvocationHandler接口的子类实例
ClassLoader loader用来指明生成代理对象使用哪个类装载器,(Proxy.class.getClassLoader())
Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,
InvocationHandler h用来指明产生的这个代理对象要做什么事情。
下面来看一个例子:
先定义一个接口:Person.java
public interface Person {
String sing(String musicName);
String speak(String text);
}
给出一个实现类:薛之谦 XueZhiQian.java
public class XueZhiQian implements Person {
@Override
public String sing(String musicName) {
System.out.println("薛之谦唱了 "+musicName);
return "歌曲唱完,谢谢各位!";
}
@Override
public String speak(String text) {
System.out.println("薛之谦说了 "+text);
return "话已讲完,谢谢各位!";
}
}
生成代理对象的代理类:XueZhiQianProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class XueZhiQianProxy {
//要代理的对象
private Person xzq = new XueZhiQian();
public Person getProxy(){
return (Person)Proxy.newProxyInstance(XueZhiQianProxy.class.getClassLoader(),
xzq.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("sing")){
System.out.println("找薛之谦唱歌需要先交2W!");
return method.invoke(xzq, args);
}
if(method.getName().equals("speak")){
System.out.println("找薛之谦唱歌需要先交10W!");
return method.invoke(xzq, args);
}
return null;
}
});
}
}
测试代码:
public class Test01 {
public static void main(String[] args) {
XueZhiQianProxy proxy = new XueZhiQianProxy();
Person p = proxy.getProxy();
String s1 = p.sing("演员");
System.out.println(s1);
String s2 = p.speak("段子");
System.out.println(s2);
}
}
测试结果:
找薛之谦唱歌需要先交2W!
薛之谦唱了 演员
歌曲唱完,谢谢各位!
找薛之谦唱歌需要先交10W!
薛之谦说了 段子
话已讲完,谢谢各位!
以上是关于Java基础加强——动态代理的主要内容,如果未能解决你的问题,请参考以下文章
第17天(基础加强_注解_类加载器_动态代理)_学习目标版本
JAVAWEB学习笔记25_基础加强:类加载器注解 @xxx和动态代理