Java——代理的实现(静态代理和动态代理)

代理

代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象。如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目标对象功能的特点也为多人所用。

静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。

接口Business

public interface Business {
    void execute();
}

接口实现类BusinessImp

public class BusinessImp implements Business {
    public void execute() {
        System.out.println("业务处理");
    }

}

代理实现BusinessProxy

public class BusinessProxy implements Business {    
    private Business businessImp;   
    public BusinessProxy(Business businessImp) {
        super();
        this.businessImp = businessImp;
    }
    public void execute() {
        System.out.println("业务处理前");
        businessImp.execute();
        System.out.println("业务处理后");
    }
}

使用和结果

public class App 
{
    public static void main( String[] args )
    {
       Business businessImp=new BusinessImp();
       BusinessProxy businessProxy=new BusinessProxy(businessImp);
       businessProxy.execute();
    }
}

输出:
结果
总结:
1. 优点:可以做到不对目标对象进行修改的前提下,对目标对象进行功能的扩展和拦截。
2. 缺点:因为代理对象,需要实现与目标对象一样的接口,会导致代理类十分繁多,不易维护,同时一旦接口增加方法,则目标对象和代理类都需要维护。

JDK动态代理

jdk动态代理是由java内部的反射机制来实现的,需要实现类通过接口定义业务方法,利用JDK的API,动态的在内存中构建代理对象。

接口Business

public interface Business {
    void execute();
}

接口实现类BusinessImp

public class BusinessImp implements Business {
    public void execute() {
        System.out.println("业务处理");
    }

}

代理实现BusinessInvocationHandler

public class BusinessInvocationHandler implements InvocationHandler {
    private Object target;
    public BusinessInvocationHandler(Object target) {
        super();
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("业务处理前");
        Object result=method.invoke(target, args);
        System.out.println("业务处理后");
        return result;
    }
    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader()
                , target.getClass().getInterfaces(), this);
    }

}
  1. 实现InvocationHandler接口,重写public Object invoke(Object proxy, Method method, Object[] args)方法。
  2. 使用Proxystatic Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )方法实现代理。ClassLoader loader指定当前目标对象使用类加载器;Class<?>[] interfaces是目标对象实现的接口的类型;InvocationHandler h是事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入。

使用和结果

public class App 
{
    public static void main( String[] args )
    {
        Business businessImp=new BusinessImp();
        BusinessInvocationHandler businessInvocationHandler=new BusinessInvocationHandler(businessImp);
        Business businessProxy=(Business)businessInvocationHandler.getProxy();
        businessProxy.execute();
    }
}

输出:
结果
总结:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。

CGLIB动态代理

静态代理和JDK动态代理都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理。cglib是针对类来实现代理的,它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。因为采用的是继承,所以不能对final修饰的类进行代理。

使用Maven导入相关jar包

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.4</version>
</dependency>

目标类BusinessImp

public class BusinessImp {
    public void execute(){
        System.out.println("业务处理");
    }
}

代理实现BusinessProxy

public class BusinessProxy implements MethodInterceptor {   
    public Object getProxy(Class<?> clazz){
        Enhancer enchancer=new Enhancer();
        enchancer.setSuperclass(clazz);
        enchancer.setCallback(this);
        return enchancer.create();
    }
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("业务处理前");
        Object result=proxy.invokeSuper(obj, args);
        System.out.println("业务处理后");
        return result;
    }
}
  1. 实现MethodInterceptor接口,重写public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)方法,该方法为回调方法,在该方法中使用proxy.invokeSuper(obj, args)执行目标对象的方法。
  2. 使用Enhancer来创建子类,setSuperclass(clazz)方法设置了父类,setCallback(this)方法设置了回调方法,create()方法创建了子类。

使用和结果

public class App 
{
    public static void main( String[] args )
    {   
        BusinessProxy businessProxy=new BusinessProxy();
        BusinessImp businessImp=(BusinessImp) businessProxy.getProxy(BusinessImp.class);
        businessImp.execute();
    }
}

输出:
结果

猜你喜欢

转载自blog.csdn.net/YINLINNEVERG/article/details/80291649