• 动态代理--jdk和cglib


    一、含义

    1、静态代理:简单,代理模式,是动态代理的理论基础。常见使用在代理模式

    2、jdk动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用业务方法前调用InvocationHandler处理。代理类必须实现InvocationHandler接口,并且,JDK动态代理只能代理实现了接口的类,没有实现接口的类是不能实现JDK动态代理

    3、cglib动态代理:可以直接代理类,使用字节码技术,不能对 final类进行继承。使用了动态生成字节码技术。

    二、区别对比

    JDK与Cglib动态代理对比?

    1、JDK动态代理只能代理实现了接口的类,没有实现接口的类不能实现JDK的动态代理;

    2、Cglib动态代理是针对类实现代理的,运行时动态生成被代理类的子类拦截父类方法调用,因此不能代理声明为final类型的类和方法;

    动态代理和静态代理的区别?

    1、静态代理在代理前就知道要代理的是哪个对象,而动态代理是运行时才知道;

    2、静态代理一般只能代理一个类,而动态代理能代理实现了接口的多个类;

    Spring如何选择两种代理模式的?

    1、如果目标对象实现了接口,则默认采用JDK动态代理;

    2、如果目标对象没有实现接口,则使用Cglib代理;

    3、如果目标对象实现了接口,但强制使用了Cglib,则使用Cglib进行代理

    三、.代码实现步骤

    1、 jdk动态代理

    步骤:

    1.1、编写需要被代理的类和接口(我这里就是OrderServiceImpl、OrderService);

    1.2、编写代理类(例如我这里的DynamicLogProxy),需要实现InvocationHandler接口,重写invoke方法;

    1.3、使用Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)动态创建代理类对象,通过代理类对象调用业务方法。

    2.cglib动态代理

    cglib是针对类来实现代理的,它会对目标类产生一个代理子类,通过方法拦截技术对过滤父类的方法调用。代理子类需要实现MethodInterceptor接口

    四、代码具体实现

    public interface UserService {
    
    	void saveUser();
    }
    

      

    public class UserServiceImpl implements UserService {
    
    	
    	@Override
    	public void saveUser() {
    		System.out.println("IoC 演示 之UserService" );
    	}
    
    }
    

      

    package com.kkb.spring.utils;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import com.kkb.spring.service.UserService;
    import com.kkb.spring.service.UserServiceImpl;
    
    /**
     * 主要作用就是生成代理类
     * 
     * @author think
     *
     */
    public class MyProxyUtils {
    
    	/**
    	 * 使用JDK的动态代理实现 它是基于接口实现的
    	 * 
    	 * @param serviceImpl
    	 * @return
    	 */
    	public static UserService getProxy(UserService service) {
    
    		// Proxy是JDK中的API类
    		// 第一个参数:目标对象的类加载器
    		// 第二个参数:目标对象的接口
    		// 第二个参数:代理对象的执行处理器
    		UserService userService = (UserService) Proxy.newProxyInstance(service.getClass().getClassLoader(),
    				service.getClass().getInterfaces(), new InvocationHandler() {
    
    					@Override
    					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    						System.out.println("记录日志-开始");
    
    						// 下面的代码,是反射中的API用法
    						// 该行代码,实际调用的是目标对象的方法
    						Object object = method.invoke(service, args);
    
    						System.out.println("记录日志-结束");
    						return object;
    					}
    				});
    
    		return userService;
    	}
    
    	/**
    	 * 使用CGLib动态代理技术实现 它是基于继承的方式实现的
    	 * 
    	 * @param service
    	 * @return
    	 */
    	public static UserService getProxyByCgLib(UserService service) {
    
    		// 创建增强器
    		Enhancer enhancer = new Enhancer();
    		// 设置需要增强的类的类对象
    		enhancer.setSuperclass(UserServiceImpl.class);
    
    		// 设置回调函数
    		enhancer.setCallback(new MethodInterceptor() {
    
    			// MethodProxy:代理之后的对象的方法引用
    			@Override
    			public Object intercept(Object object, Method method, Object[] arg, MethodProxy methodProxy)
    					throws Throwable {
    
    				long start = System.currentTimeMillis();
    				System.out.println("记录程序开始时间..." + start);
    
    				// 因为代理对象是目标对象的子类
    				// 该行代码,实际调用的是目标对象的方法
    				// object :代理对象
    				Object object2 = methodProxy.invokeSuper(object, arg);
    
    				long end = System.currentTimeMillis();
    				System.out.println("记录程序结束时间..." + end);
    				System.out.println("记录程序执行总时长..." + (end - start));
    				return object2;
    			}
    		});
    
    		// 获取增强之后的代理对象
    		UserService userService = (UserService) enhancer.create();
    		return userService;
    	}
    }
    

      

    package com.kkb.spring.test;
    
    import org.junit.Test;
    
    import com.kkb.spring.service.UserService;
    import com.kkb.spring.service.UserServiceImpl;
    import com.kkb.spring.utils.MyProxyUtils;
    
    public class TestProxy {
    
    	@Test
    	public void testJDKProxy() {
    		
    		//创建目标对象
    		UserService service = new UserServiceImpl();
    		
    		//生成代理对象
    		UserService proxy = MyProxyUtils.getProxy(service);
    		
    		//调用目标对象的方法
    		service.saveUser();
    		
    		System.out.println("===============");
    		//调用代理对象的方法
    		proxy.saveUser();
    	}
    	@Test
    	public void testCgLibProxy() {
    		
    		//创建目标对象
    		UserService service = new UserServiceImpl();
    		
    		//生成代理对象
    		UserService proxy = MyProxyUtils.getProxyByCgLib(service);
    		
    		//调用目标对象的方法
    		service.saveUser();
    		
    		System.out.println("===============");
    		//调用代理对象的方法
    		proxy.saveUser();
    	}
    }
    

      

  • 相关阅读:
    webstorm 2017 激活破解 最新 2018
    phpexcel 导出xsl乱码
    微信小程序的z-index在苹果ios无效
    onenote架设在局域网服务器
    .gitignore忽略多层文件夹用**
    phpstorm 使用xdebug断点
    Phpstudy 无法启动mysql
    git使用kdiff3合并乱码问题
    小程序回退刷新操作
    Navicat 连接远程服务器mysql 长时间不操作会连接很久
  • 原文地址:https://www.cnblogs.com/currystar/p/11050891.html
Copyright © 2020-2023  润新知