Java 动态代理

Java动态代理机制详解

标签(空格分隔): 动态代理 cglib jdk


动态代理

使用场景

可以在运行的时候才切入改变类的方法,而不需要预先定义它。通过动态代理,我们可以实现类的增强,可以像AOP那样在方法执行之前,或者之后,执行安全、日志等操作

例如依赖注入的@Bean、@Autowired,事务注解@Transactional等都有用到,换言之就是Srping的AOP(切面编程)。

JDK动态代理

基于接口代理,凡是类的方法非public修饰,或者用了static关键字修饰,那这些方法都不能被Spring AOP增强

原理

在获取到代理类的classLoader及相应的接口之后,可以获取到代理类的Class对象,通过反射获取到构造方法,new一个对象绑定到InvocationHandler上。

#Proxy类
public static Object newProxyInstance(ClassLoader loader,
            Class<?>[] interfaces, InvocationHandler h)
  • loder,选用的类加载器。一般都会用加载代理对象的类加载器。
  • interfaces,被代理的类所实现的接口,这个接口可以是多个。
  • h,绑定代理类的一个方法。

loader跟interfaces基本决定了这个代理类的所属对象

InvocationHandler在调用代理类的方法时会执行一个绑定的方法,同时会替代原本方法的结果返回。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //会导致死循环
    method.invoke(proxy, args)
    //object为被代理的对象
    method.invoke(object,args)
}

proxy是代理对象,当该对象的方法被调用时,会触发InvocationHandler中的invoke方法。

例子

public interface Person {

    public void say();
}
public class Men implements Person {

    @Override
    public void say() {
        System.out.println("hello, i am a man");
    }
}
        Men man = new Men();
        Person person = (Person) Proxy.newProxyInstance(
        man.getClass().getClassLoader(), 
        man.getClass().getInterfaces(), 
        new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before say method begin");
                method.invoke(man,args);
                System.out.println("after say method finish");
                return null;
            }
        });
        person.say();

结果

before say method begin
hello, i am a man
after say method finish

Cglib动态代理

基于子类代理,凡是类的方法使用了private、static、final修饰,那这些方法都不能被Spring AOP增强

JDK动态代理,发现其真实对象必须提供接口才可以使用。在一些不提供接口的环境中,只能采用一些别的第三方技术,比如CGLIB动态代理。

    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>2.2.2</version>
    </dependency>
public class CglibProxyExample implements MethodInterceptor {

    public Object getProxy(Class clz){
        //CGLIB enhancer增强类对象
        Enhancer enhancer = new Enhancer();
        //设置增强类型
        enhancer.setSuperclass(clz);
        //定义代理对象为当前对象,要求当前对象实现MethodInterceptor方法
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    /**
     * @param proxy 代理对象
     * @param method 方法
     * @param args 方法参数
     * @param methodProxy 方法代理
     * @return 代理逻辑返回
     * @throws Throwable 抛出异常
     */
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        System.out.println("before say method begin");
        Object retObj = methodProxy.invokeSuper(proxy,args);
        System.out.println("after say method finish");
        return retObj;
    }
}
    CglibProxyExample cglibProxyExample = new CglibProxyExample();
    Men men = (Men)cglibProxyExample.getProxy(Men.class);
    men.say();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值