动态代理

动态代理,区别与代理模式的静态代理,静态代理往往通过构造函数并返回一个真实的被代理对象,然后执行被代理对象的方法,因此不能额外执行更多的操作。静态代理最主要的是引入明确的被代理对象,程序在编译阶段就需要知道要代理的对象,因此有很多局限性。而动态代理则是在实现阶段并不关心要代理谁,在程序运行阶段才指定代理的对象。现在有一个非常流行的技术叫面向切面编程,其核心就是采用了动态代理机制。对于日志,事务,权限都可以在设计阶段不用考虑,而在设计后通过AOP的方式切入。

抽象主题,主要是定义需要干的事情

public interface Subject {
//业务操作s
    public void doSomething(String strs);
}

真实主题

public class RealSubject implements Subject {

    @Override
    public void doSomething(String strs) {
        System.out.println("do something--------------->"+strs);
    }

}
//动态代理的handler类

public class MyInvocationHander implements InvocationHandler {
private Object target=null;

    public MyInvocationHander(Object obj) {
    super();
    this.target = obj;
}

    /**
     * 代理方法
     * 所有通过代理的方法都通过invoke方法调用
     * **/
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub
        return method.invoke(this.target, args);
    }

}

 

//动态代理类

public class DynamicProxy<T> {
@SuppressWarnings("unchecked")
public static <T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler ){
    if(true) {
        //执行前置通知
        (new BeforeAdvice()).exec();
    }
    return (T) Proxy.newProxyInstance(loader, interfaces,  handler);
}
}

//通知接口以及实现

public interface IAdvice {
public void exec();
}

public class BeforeAdvice implements IAdvice {

    @Override
    public void exec() {
        System.out.println("我是前置通知,我给执行了");

    }

}
 

//动态代理场景测试

public class Client {
public static void main(String[] args) {
    //定义一个主题
    Subject subject=new RealSubject();
    //定义一个handler,处理工作
    InvocationHandler handler=new MyInvocationHander(subject);
    
//定义主题的代理、
    Subject proxy=DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
        proxy.doSomething("finished");    
}
}

 

执行结果

我是前置通知,我给执行了
do something--------------->finished

刚才的动态代理只是通用的一个代理类,没有业务意义,我们可以继承这个从而产生一个实现类来处理业务

public class SubjectDynamicProxy extends DynamicProxy{
    public static <T> T newProxyInstance(Subject subject) {
        ClassLoader loader=subject.getClass().getClassLoader();
        Class<?>[] classes=subject.getClass().getInterfaces();
        InvocationHandler handler=new MyInvocationHander(subject);
        
        
        return newProxyInstance(loader, classes, handler);
        
    }
}

 

具体的代理就更加简单

public class Client {
public static void main(String[] args) {
    
    //定义一个主题
    Subject subject=new RealSubject();
    //定义一个handler,处理工作
    InvocationHandler handler=new MyInvocationHander(subject);
    
     //定义主题的代理、
    Subject proxy=DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
    //第二种代理业务
    Subject proxy2=SubjectDynamicProxy.newProxyInstance(subject);
    
    
    proxy.doSomething("finished");    
    proxy2.doSomething("second business finished");
}
}

 

在不改变原有代码的基础上增强或者控制对象的行为。要实现动态代理的首要条件是被代理类必须实现一个接口。现在有一些代理技术比如,CGLIB不用实现接口也可以实现对象的动态代理。

jdk自带的反射代理类java.lang.reflect.Proxy的newProxyInstance 可以为我们动态生成代理对象,其原理是通过动态生成并装载代理类的字节码。cglib与jdk的动态代理不同,下一篇将会介绍cglib和JDK动态代理的不同之处和优缺点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值