JDK代理和CGLib动态代理

JDK代理和CGLib动态代理

JDK代理和CGLib

  • jdk代理好处是不需要导入第三方jar包。但目标对象必须实现接口,是基于接口实现。利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
  • CGLib基于第三方jar包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。所以该类或方法最好不要声明成final。

代码实现

注解:
用于判断那些方法需要代理,或不需要代理

package com.example.java_test.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}

接口:

package com.example.java_test.proxy;

import com.example.java_test.annotation.Test;

public interface UserService {

    void queryAll();

	// 当为JDK动态代理时,拿到的是接口上的注解
    @Test
    void saveUser();

}

接口实现:

package com.example.java_test.proxy.impl;

import com.example.java_test.annotation.Test;
import com.example.java_test.proxy.UserService;

public class UserServiceImpl implements UserService {

    @Override
    public void queryAll() {
        System.out.println("查询出所有的学生。。。。。");
    }

    @Override
    // CGLib代理时,拿到的是此处的注解
    @Test
    public void saveUser() {
        System.out.println("保存学生信息");
    }
}

JDK代理类:

package com.example.java_test.proxy;

import com.example.java_test.annotation.Test;
import com.example.java_test.proxy.impl.UserServiceImpl;


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

public class JDKProxyTest implements InvocationHandler {


    /**
     * 目标对象
     */
    private Object target;

    public Object newProxy(Object target){
        //接收业务实现类对象参数
        this.target = target;

        //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
        //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        String name = method.getName();
//        if (!name.equals("queryAll")){
//            method.invoke(target,args);
//
//        }else {
//            System.out.println("调用方法前的操作");
//            method.invoke(target,args);
//            System.out.println("调用方法后的操作");
//        }
        Test[] annotationsByType = method.getAnnotationsByType(Test.class);
        if (annotationsByType.length > 0){
            System.out.println("调用方法前的操作");
            method.invoke(target,args);
            System.out.println("调用方法后的操作");
        }else {
            method.invoke(target,args);
        }

        return null;
    }


    public static void main(String[] args) {

        UserServiceImpl userService = new UserServiceImpl();
        JDKProxyTest proxyTest = new JDKProxyTest();
        UserService proxy = (UserService)proxyTest.newProxy(userService);
        proxy.queryAll();
    }
}

CGLib代理实现类:

package com.example.java_test.proxy;

import com.example.java_test.annotation.Test;
import com.example.java_test.proxy.impl.UserServiceImpl;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGLibProxyTest implements MethodInterceptor {


    private Object target;//业务类对象,供代理方法中进行真正的业务方法调用

    //相当于JDK动态代理中的绑定
    public Object getInstance(Object target) {
        //给业务对象赋值
        this.target = target;
        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer();
        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(this.target.getClass());
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    	// 获取方法上的注解
        Test[] annotation = method.getAnnotationsByType(Test.class);
        if (annotation != null) {
            //调用业务类(父类中)的方法
            methodProxy.invokeSuper(o, objects);
        } else {
            System.out.println("处理之前的操作");
            //调用业务类(父类中)的方法
            methodProxy.invokeSuper(o, objects);
            System.out.println("调用后操作");
        }
        return null;
    }

    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        CGLibProxyTest proxyTest = new CGLibProxyTest();
        UserServiceImpl proxy = (UserServiceImpl) proxyTest.getInstance(userService);
        proxy.queryAll();
    }
}

当我们代理时,可能不会对类中所有的方法进行代理,可能只是对其中的一部分功能增强,可以根据方法名,或者是注解去实现部分增强。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值