Java设计模式(七) Spring AOP JDK动态代理 VS. cglib

  原创文章,转载请务必将下面这段话置于文章开头处。
  本文转发自Jason’s Blog原文链接 http://www.jasongj.com/design_pattern/dynamic_proxy_cglib/

静态代理 VS. 动态代理

静态代理,是指程序运行前就已经存在了代理类的字节码文件,代理类和被代理类的关系在运行前就已经确定。

上一篇文章《Java设计模式(六) 代理模式 VS. 装饰模式》所讲的代理为静态代理。如上文所讲,一个静态代理类只代理一个具体类。如果需要对实现了同一接口的不同具体类作代理,静态代理需要为每一个具体类创建相应的代理类。

动态代理类的字节码是在程序运行期间动态生成,所以不存在代理类的字节码文件。代理类和被代理类的关系是在程序运行时确定的。

JDK动态代理

JDK从1.3开始引入动态代理。可通过java.lang.reflect.Proxy类的静态方法Proxy.newProxyInstance动态创建代理类和实例。并且由它动态创建出来的代理类都是Proxy类的子类。

定义代理行为

代理类往往会在代理对象业务逻辑前后增加一些功能性的行为,如使用事务或者打印日志。本文把这些行为称之为代理行为

使用JDK动态代理,需要创建一个实现java.lang.reflect.InvocationHandler接口的类,并在该类中定义代理行为。

package com.jasongj.proxy.jdkproxy;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SubjectProxyHandler implements InvocationHandler {
   

  private static final Logger LOG = LoggerFactory.getLogger(SubjectProxyHandler.class);

  private Object target;

  @SuppressWarnings("rawtypes")
  public SubjectProxyHandler(Class clazz) {
    try {
      this.target = clazz.newInstance();
    } catch (InstantiationException | IllegalAccessException ex) {
      LOG.error("Create proxy for {} failed", clazz.getName());
    }
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    preAction();
    Object result = method.invoke(target, args);
    postAction();
    return result;
  }

  private void preAction() {
    LOG.info("SubjectProxyHandler.preAction()");
  }

  private void postAction() {
    LOG.info("SubjectProxyHandler.postAction()");
  }

}

从上述代码中可以看到,被代理对象的类对象作为参数传给了构造方法,原因如下
- 如上文所述,动态代理可以代理多种类,而且具体代理哪种类并非台静态代理那样编译时确定,而是在运行时指定
- 之所以不传被代理类的实例而是传类对象,是为了与上文《Java设计模式(六) 代理模式 VS. 装饰模式》吻合——被代理对象不由客户端创建而由代理创建,客户端甚至都不需要知道被代理对象的存在。具体传被代理类的实例还是传类对象,并无严格规定
- 一些讲JDK动态代理的例子会专门使用一个public方法去接收该参数。但笔者个人认为最好不要在具体类中实现未出现在接口定义中的public方法

注意,SubjectProxyHandler定义的是代理行为而非代理类本身。实际上代理类及其实例是在运行时通过反射动态创建出来的。

JDK动态代理使用方式

代理行为定义好后,先实例化SubjectProxyHandler(在构架方法中指明被代理类),然后通过Proxy.newProxyInstance动态创建代理类的实例。

package com.jasongj.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import com.jasongj.proxy.jdkproxy.SubjectProxyHandler;
import com.jasongj.subject.ConcreteSubject;
import com.jasongj.subject.ISubject;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值