Spring动态代理(JDK+CGLIB)

前言

强烈推荐 B站 宝藏男孩 遇见狂神说

JDK动态代理(基于接口)

  • 学习之前,主要了解**代理模式**

  • 用一个简单的例子来了解:

1、创建UserDao接口


public interface UserDao {

   void save();

   void delete();
}

2、实现接口


public class UserDaoImpl implements UserDao {

    public void save() {
        System.out.println("保存");
    }

    public void delete() {
        System.out.println("删除");
    }
}

3、方面,公共的组件


public class MyAspect {

    public void before(){
        System.out.println("before方法");
    }

    public void after(){
        System.out.println("after方法");
    }


}

4.代理类

  • InvocationHandler 接口
  • 是proxy代理实例的调用处理程序实现的一个接口,需要实现

  • proxy是代理对象,method目标对象方法,args目标对象方法的参数
  • .Proxy类就是用来创建一个代理对象的类

public Object invoke(Object proxy, Method method, Object[] args)


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

public class MyProxy implements InvocationHandler {

     private UserDao userDao;
     private MyAspect myAspect;

    public MyProxy(UserDao userDao, MyAspect myAspect) {
        this.userDao = userDao;
        this.myAspect = myAspect;
    }

//创建代理对象
    public Object getProxy(){

        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                userDao.getClass().getInterfaces(),this);
    }


    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        myAspect.before();
        method.invoke(userDao,args);
        System.out.println("方法名:"+method.getName());
        myAspect.after();
        return null;
    }
}

5、测试

public class Test {
    public static void main(String[] args) {

//       被代理类,真实类
        UserDao userDao = new UserDaoImpl();


//      方面,抽出的公共方法
        MyAspect aspect = new MyAspect();


//      代理类
        MyProxy proxy = new MyProxy(userDao,aspect);

        UserDao user = (UserDao) proxy.getProxy();

        user.save();

CGLIB动态代理(基于类)

  • MethodInterceptor

实现MethodInterceptor 接口,在调用目标对象的方法时,
就可以实现在调用方法之前、调用方法过程中、调用方法之后对其进行控制。

  • Enhancer

Enhancer允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作。

代理类



import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;


/*
* 实现MethodInterceptor 接口,在调用目标对象的方法时,
* 就可以实现在调用方法之前、调用方法过程中、调用方法之后对其进行控制。
* */
public class MyProxy<T> implements MethodInterceptor {

    private T byProxy;
    private MyAspect myAspect;

    public MyProxy(T byProxy, MyAspect myAspect) {
        this.byProxy = byProxy;
        this.myAspect = myAspect;
    }


    public T getProxy(){

//     Enhancer可以用来为无接口的类创建代理。
//   它的功能与java自带的Proxy类挺相似的

//        通过Enhancer创建代理类
        Enhancer enhancer = new Enhancer();

//        设置需要代理的类
        enhancer.setSuperclass(UserDaoImpl.class);

        enhancer.setCallback(this);

        T obj = (T)enhancer.create();
        return obj;
    }


    /*
    *  Method method  调用的被代理对象的方法
    *
    * */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

       myAspect.before();
       method.invoke(byProxy,objects);
       myAspect.after();

        return null;
    }
}

测试

public class Test {
    public static void main(String[] args) {

//        被代理对象
        UserDaoImpl userDao = new UserDaoImpl();

//        方面
       MyAspect myAspect = new MyAspect();

//       代理类
        MyProxy<UserDaoImpl> myProxy = new MyProxy<UserDaoImpl>(userDao,myAspect);


       UserDaoImpl userDao1 =  myProxy.getProxy();

       userDao1.save();
       userDao1.delete();
    }
}

总结
1、两者实现动态代理,主要是在代理类的实现接口不同,创建代理类的类不同

jdk实现InvocationHandler接口,Proxy创建代理类

cglib实现MethodInterceptor接口,Enhancer 创建代理类

共同成长,共同进步~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值