【Javaspring学习笔记】动态代理

 

 

在学习Spring的时候,我们知道Spring主要有两大思想,一个是IOC,另一个就是AOP,对于IOC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。

动态代理有两种方式:

1、jdk动态代理是由java内部的反射机制来实现的

2、cglib动态代理底层则是借助asm来实现的。

一、JDK动态代理,创建的效率高

jdk动态代理是jdk原生就支持的一种代理方式,它的实现原理,就是通过让target类和代理类实现同一接口,代理类持有target对象,来达到方法拦截的作用,这样通过接口的方式有两个弊端,一个是必须保证target类有接口,第二个是如果想要对target类的方法进行代理拦截,那么就要保证这些方法都要在接口中声明,实现上略微有点限制。

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

proxy:  指代我们所代理的那个真实对象
method:  指代的是我们所要调用真实对象的某个方法的Method对象
args:  指代的是调用真实对象某个方法时接受的参数

这样就定义了一个动态代理类

package service;

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

public class Temp implements InvocationHandler {
    private Object object;



    /**
     * 生成代理类
     * @return
     */
    public Object getUser()
    {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                object.getClass().getInterfaces(),this);

    }
    /**
     *
     * @param proxy 生成的代理类
     * @param method 代理类的调用处理程序的方法对象
     * @param args
     * @return
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object result=method.invoke(object,args);
        return result;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

在invoke里面可以写需要执行的逻辑

 

调用:

package test;

import service.Service;
import service.Serviceimpl;
import service.Temp;

public class Proxy_test {
    public static void main(String[] args) {
        Serviceimpl serviceimpl=new Serviceimpl();//新建一个实体类
     
        Temp temp=new Temp();  //代理类
        
      temp.setObject(serviceimpl); //传入实体
        
        Service service=( Service)temp.getUser();//接口类接受收
        
        service.add();//执行公有方法
    }

}

二、cglib动态代理 ,执行的效率高

使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能

 

1、写被代理的类

/**
 * @author 贺文杰
 * 2018/8/1 15:45
 */
public class UserServiceImpl {
    public String say(String name){
        System.out.println(name);
        return name;
    }
}

2、写Cglb类

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

import java.lang.reflect.Method;

/**
 * @author 贺文杰
 * 2018/8/1 16:02
 */
public class CglibProxy implements MethodInterceptor {
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println("执行前");
        Object object= methodProxy.invokeSuper(o,objects);
        System.out.println("执行后");
        return null;
    }
}

 

3、执行:

import net.sf.cglib.proxy.Enhancer;

/**
 * @author 贺文杰
 * 2018/8/1 16:01
 */
public class Main {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        Enhancer enhancer = new Enhancer();
        //给单独一个类设置超类
        enhancer.setSuperclass(UserServiceImpl.class);
        //设置回调
        enhancer.setCallback(proxy);
        UserServiceImpl userService=(UserServiceImpl) enhancer.create();
        String string=userService.say("贺文杰");
        System.out.println(string);

    }
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值