java动态代理 jdk和cglib的实现

综述:

      代理是一种设计模式,一种思想理念,通俗的说,就是一种观念。代理的实现方式有多种:静态代理,动态代理。

静态代理:

      静态代理的实现非常简单,在业务类外面再包一层代理类,所有对外的接口都通过代理类进行调用,外部不知道内部业务类的名称等,保证了内部类的安全。本文不做详细说明。

动态代理:

      java动态代理实现方式有:Java自带的jdk,javax包下的cglib,以及没用过的javaassist。

jdk实现:

      jdk实现是java自带的功能,因为是自带的所以性能应该是最好的。jdk通过反射实现,只能代理目标接口,不能代理实现类。需要继承InvocationHandler接口,使用Proxy实例化。

jdk示例:

*      public class FacadeProxy implements InvocationHandler {
*          Object facade;//可以代理任何类!如果需要代理指定类,在复制的时候个性化赋值!
*
*          public Object createInstance(Object facade){
*              this.facade = facade;
*              //底部调用了构造器的newInstance实例化
*              return Proxy.newProxyInstance(facade.getClass().getClassLoader(), facade.getClass().getInterfaces(), this);
*
*          }
*
*          public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
*              //也就这一步有用,invoke通过实例进行调用
*              method.invoke(facade, objects);//可以打日志等
*              return null;
*           }
*       }

 

*     public static void main(String[] args) {
*         FacadeProxy fp = new FacadeProxy();
*         //对象实例来自反射,而不是new。
*         //由于想要实现代理所有类的效果,这里new实例是具体的;
*         //如果要实现对外安全的效果,里面为空就行,new在代理类里面去具体写上!已验证!
*         Facade facade = (Facade) fp.createInstance(new FacadeImpl());
*         facade.fun(10);
*     }

 

Cglib实现:

      cglib处于javax包下,通过asm包加载目标类字节码,通过改变字节码创建子类实现。可以代理类,但是肯定不能类里面private方法。需要继承MethodInterceptor接口,使用Enhancer实例化。

Cglib示例:

*  public class FacadeProxyByCglib implements MethodInterceptor { 功能同上!!!
*
*     Object facade;
*
*     public Object createInstance(Object facade){
*         this.facade = facade;
*         return Enhancer.create(facade.getClass(), this);
*
*     }
*
*     @Override
*     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
*         method.invoke(facade, objects);
*         return null;
*     }
* }

反射:

      在运行过程中可以获得一个类的方法与属性,并可以调用一个实例的方法与属性。通用方式为:

      1、Class<?> clazz = Class.forName(""); 类.class;实例.getClass();

      2、由clazz可以获得方法、属性等。通用方法如getMethod可以获得包括父类在内的public方法,如果要获得private等所有的方法只能用getDeclaredMethod等用decalared修饰的方法,不能获得父类的。

      3、如果要操作2获得的方法,需要在实例里面,clazz.newInstance();;在jdk9之后这个方法被注解,大概是建议使用构造器的实现方式:constructor.newInstance();

      4、方法、属性需要setAccessible(true):如果是打算操作private方法、属性等,需要设置这个可访问。

      5、正常调用method.invoke(实例,参数);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值