
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
昆明达内培训的老师今天给大家讲动态代理可以使代理模式更加灵活
Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发。昆明达内培训的老师知道一个静态代理是通过主题角色(Proxy)和具体主题角色(Real Subject)共同实现主题角色(Subject)的逻辑的,只是代理角色把相关的执行逻辑委托给了具体角色而已,一个简单的静态代理如下所示:
interface Subject {
//定义一个方法
public void request();
}
//具体主题角色
class RealSubject implements Subject {
//实现方法
@Override
public void request() {
//实现具体业务逻辑
}
}
class Proxy implements Subject {
//要代理那个实现类
private Subject subject = null;
//默认被代理者
public Proxy() {
subject = new RealSubject();
}
//通过构造函数传递被代理者
public Proxy(Subject _subject) {
subject = _subject;
}
@Override
public void request() {
before();
subject.request();
after();
}
//预处理
private void after() {
// doSomething
}
//善后处理
private void before() {
// doSomething
}
}
这是一个简单的静态代理。Java还提供了java.lang.reflect.Proxy用于实现动态代理:只要提供一个抽象主题角色和具体主题角色,就可以动态实现其逻辑的,其实例代码如下:
interface Subject {
//定义一个方法
public void request();
}
//具体主题角色
class RealSubject implements Subject {
//实现方法
@Override
public void request() {
//实现具体业务逻辑
}
}
class SubjectHandler implements InvocationHandler {
//被代理的对象
private Subject subject;
public SubjectHandler(Subject _subject) {
subject = _subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//预处理
System.out.println("预处理...");
//直接调用被代理的方法
Object obj = method.invoke(subject, args);
//后处理
System.out.println("后处理...");
return obj;
}
}
注意这里没有代理主题角色,取而代之的是SubjectHandler作为主要的逻辑委托处理,其中invoke方法是接口InvocationHandler定义必须实现的,它完成了对真实方法的调用。
昆明达内培训的老师来详细解释一下InvocationHandler接口,动态代理是根据被代理的接口生成的所有方法的,也就是说给定一个或多个接口,动态代理会宣称“我已经实现该接口下的所有方法了”,那大家想想看,动态代理是怎么才能实现接口中的方法呢?在默认情况下所有方法的返回值都是空的,是的,虽然代理已经实现了它,但是没有任何的逻辑含义,那怎么办?好办,通过InvocationHandler接口的实现类来实现,所有的方法都是由该Handler进行处理的,即所有被代理的方法都由InvocationHandler接管实际的处理任务。
我们开看看动态代理的场景,代码如下:
public static void main(String[] args) {
//具体主题角色,也就是被代理类
Subject subject = new RealSubject();
//代理实例的处理Handler
InvocationHandler handler =new SubjectHandler(subject);
//当前加载器
ClassLoader cl = subject.getClass().getClassLoader();
//动态代理
Subject proxy = (Subject) Proxy.newProxyInstance(cl,subject.getClass().getInterfaces(),handler);
//执行具体主题角色方法
proxy.request();
}
此时就实现了,不用显式创建代理类即实现代理的功能,例如可以在被代理的角色执行前进行权限判断,或者执行后进行数据校验。
动态代理很容易实现通用的代理类,只要在InvocationHandler的invoke方法中读取持久化的数据即可实现,而且还能实现动态切入的效果,这也是AOP(Aspect Oriented Programming)变成理念。