代理原理及实现

  1. 代理模式。
    代理模式:为其他对象提供一种代理以控制对这个对象的访问。这段话比较官方,但我更倾向于用自己的语言理解:比如A对象要做一件事情,在没有代理前,自己来做,在对A代理后,由A的代理类B来做。代理其实是在原实例前后加了一层处理,这也是AOP的初级轮廓。
  2. 静态代理原理及实践。
    静态代理模式:静态代理说白了就是在程序运行前就已经存在代理类的字节码文件,代理类和原始类的关系在运行前就已经确定。
public interface IUserDao {
    void save();
    void find();
}

public class UserDaoImpl implements IUserDao {
    public void save() {
        System.out.println("保存");
    }

    public void find() {
        System.out.println("查找");
    }
}


public class UserStaticProxy   implements IUserDao{

private  IUserDao userdao =  new UserDaoImpl();
    public void save() {
        System.out.println("开启事务");
        userdao.save();
        System.out.println("提交事务");
    }

    public void find() {
       userdao.find();
    }
}

测试结果:

public class TestStaticProxy {


    public static void main(String[] args) {
        IUserDao userdao =  new UserStaticProxy();
        userdao.save();
        userdao.find();

    }

}

开启事务
保存
提交事务
查找

静态代理虽然保证了业务类只需关注逻辑本身,代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理。再者,如果增加一个方法,除了实现类需要实现这个方法外,所有的代理类也要实现此方法。增加了代码的维护成本。那么要如何解决呢?答案是使用动态代理。
3. 动态代理原理及实践。
动态代理模式:动态代理类的源码是在程序运行期间通过JVM反射等机制动态生成,代理类和委托类的关系是运行时才确定的。实例如下:

public interface IUserDao {
    void save();
    void find();
}

public class UserDaoImpl implements IUserDao {
    public void save() {
        System.out.println("保存");
    }

    public void find() {
        System.out.println("查找");
    }
}

public class ProxyFactory {

    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        //实现代理的
        InvocationHandler handler = new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object invoke ;
                String name = method.getName();
                if ("find".equals(name)) {
                    invoke = method.invoke(target, args);
                } else {
                    System.out.println("开启事务");
                    invoke = method.invoke(target, args);
                    System.out.println("提交事务");
                }
                return invoke;
            }
        };
         //这儿需要注意
        Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
        return proxy;
    }


}

测试结果:

public class ProxyFactoryTest {

    public static void main(String[] args) {
        //原对象
        IUserDao user = new UserDaoImpl();
        //代理对象
        ProxyFactory factory = new ProxyFactory(user);
        IUserDao proxyInstanceUserDao = (IUserDao)factory.getProxyInstance();
        proxyInstanceUserDao.save();
        proxyInstanceUserDao.find();
    }


}

开启事务
保存
提交事务
查找

其实是jdk动态生成了一个类去实现接口,隐藏了这个过程:

class $jdkProxy implements IUserDao{}

使用jdk生成的动态代理的前提是目标类必须有实现的接口。但这里又引入一个问题,如果某个类没有实现接口,就不能使用jdk动态代理,所以Cglib代理就是解决这个问题的。

Cglib是以动态生成的子类继承目标的方式实现,在运行期动态的在内存中构建一个子类

public class UserDao{}
//Cglib是以动态生成的子类继承目标的方式实现,程序执行时,隐藏了下面的过程
public class $Cglib_Proxy_class  extends UserDao{}

Cglib使用的前提是目标类不能为final修饰。因为final修饰的类不能被继承。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值