Java代理模式

Java代理模式

定义:

​ 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

​ 代理分为静态代理和动态代理两种:

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了

动态代理:在程序运行时,运用反射机制动态创建而成

静态代理样例

用户接口类:

package com.statics.proxy;

public interface UserDAO
{
    //用户登录接口
    public void login();
}

用户实现类:

package com.statics.proxy;

public class UserImpl implements UserDAO
{
    //用户登录操作
    @Override
    public void login()
    {
        System.out.println("user login!");
    }
}

用户代理类:

package com.statics.proxy;

public class UserProxy implements UserDAO
{
    private UserImpl userImpl;

    public UserProxy(UserImpl userImpl)
    {
        super();
        this.userImpl = userImpl;
    }
    @Override
    public void login()
    {
        //在委托类方法执行前调用相应逻辑代码
        System.out.println("check username");
        userImpl.login();
        //在委托类方法执行前调用相应逻辑代码
        System.out.println("user login result");
    }
}

代理测试类:

package com.statics.proxy;

public class Test
{
    public static void main(String[] args)
    {
        UserProxy proxy =new UserProxy(new UserImpl());
        proxy.login();
    }
}

输出结果:

check username
user login!
user login result

​ 从上面的代码中可以看出,委托类UserImpl执行login方法,其实是通过代理类UserProxy调用UserImpl类的login方法。代理类本身并没有委托类的逻辑方法,只是通过调用委托类的方法,并且在执行委托类的方法前后调用一定的业务逻辑。

​ 静态代理虽然实现了委托类的业务逻辑,但是每一个委托类必须对应一个代理类,当委托类很多的况下,代理类也会变得很多。而且代理方法除了调用的方法不一样,其他的业务逻辑都一样,这样就代码的重用率会变得很低,同时也不利于维护。因而我们引进动态代理。

动态代理

动态代理的实现方法可以分为4种:

  • JDK反射机制实现

  • CGLIB

  • Javassist
  • asm
JDK反射机制实现动态代理

UserDAO 接口类:

package com.dynamic.proxy;

public interface UserDao
{
    //唱歌的工作
    public void sing();
    //跳舞操作
    public void dance()
}

UserImpl 实现类:

package com.dynamic.proxy;

public class UserImp implements UserDao
{
    //唱歌方法实现
    @Override
    public void sing()
    {
        System.out.println("sing a song..");
    }
    //跳舞方法实现
    @Override
    public void dance()
    {
        System.out.println("begin dance!");
    }
}

JDK动态代理类:

package com.dynamic.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class UserProxyHandler implements InvocationHandler
{
    //传入委托类对象(被代理对象)
    private Object realObject;

    public UserProxyHandler(Object realObject)
    {
        super();
        this.realObject = realObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        //proxy 代理类 并非委托类
        //记录日志
        System.out.println("log/-"+method.getName()+"- begin run");
        //激活被代理类的方法
        Object result = method.invoke(realObject, args);
        //记录日志
        System.out.println("log/-"+method.getName()+"- end of run");
        return result;
    }
}

测试方法:

package com.dynamic.proxy;

import java.lang.reflect.Proxy;

public class Test
{
    public static void main(String[] args)
    {
        UserImp userImp = new UserImp();
        UserProxyHandler userProxyHandler = new UserProxyHandler(userImp);
        //生成代理类
        UserDao userProxy = (UserDao)Proxy.newProxyInstance(UserDao.class.getClassLoader(),new Class[]{UserDao.class}, userProxyHandler);
        userProxy.sing();
        userProxy.dance();
    }
}

输入结果:

log/-method:sing- begin run
sing a song..
log/-method:sing- end of run
log/-method:dance- begin run
begin dance!
log/-method:dance- end of run

​ 上面代码中,给每个被代理类的方法执行前后加入日志记录功能。动态代理与静态代理最大的区别就是,动态代理类的字节码在程序运行的过程时由Java的反射机制动态生成,无需程序员重新编码。动态代理不仅简化了编程工作,而且提高了程序的扩展性,因为通过Java的反射机制可以生成任何类的动态代理类。

​ 但是JDK动态代理需要依靠接口实现,如果被代理类没有接口的话,则动态代理无法实现。cglib方法很好的解决了这个问题。

CGLIB动态代理

UserImpl实现类:

package com.cglib.dynamic.proxy;

public class UserImp 
{
    //
    public void sing()
    {
        System.out.println("sing a song..");
    }

    public void dance()
    {
        System.out.println("begin dance..");
    }
}

cglib代理类:

package com.cglib.dynamic.proxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/*实现方法拦截器接口*/
public class UserCglibProxy implements MethodInterceptor
{

    @Override
    public Object intercept(Object object, Method method, Object[] arg2, MethodProxy    methodProxy) throws Throwable
    {
        System.out.println("log:method-" + method.getName() + "- begin runing");
        System.out.println(method.getName());
        System.out.println(methodProxy.getSuperName());
        Object result = methodProxy.invokeSuper(object, arg2);
        return result;
    }
}

测试类:

package com.cglib.dynamic.proxy;



import net.sf.cglib.proxy.Enhancer;

public class Test
{
    public static void main(String[] args)
    {
        Enhancer enhancer =new Enhancer();
        //设置要创建的动态代理的类
        enhancer.setSuperclass(UserImp.class);
        //设置回调
        enhancer.setCallback(new UserCglibProxy());

        UserImp userImp =(UserImp) enhancer.create();
        userImp.sing();
        userImp.dance();
    }
}

输出结果:

log:method-sing- begin runing
sing
CGLIB sing 0
sing a song..
log:method-dance- begin runing
dance
CGLIB dance 1
begin dance..

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值