JDK和CGLIB动态代理

接下来是我对 JDK与 CGLIB 动态代理的基本的讲解。


动态代理的主要作用: 不改变原有的代码基础上,对已有的方法进行增强。源于AOP思想中实现的技术。

1.JDK与CHLIB的不同之处

在学习这两种代理之前,我们先来对他们的差异进行一定的基本了解。

  • JDK利用拦截器(InvocationHanlder)在调用方法之前先调用InvokeHandler来处理;
  • CGLIB则是利用jar包对代理对象的类通过class文件加载进来处理。

  • 使用JDK,就要对目标对象实现接口
  • 使用CGLIB,可以不用对目标对象实现接口

本人用一个项目“登录”案例来对JDK与CGLIB动态代理的解释。

2.JDK动态代理

本次项目名【Dynammic_proxy】,JDK动态代理包,共有三个类与一个接口组成,分别为:

执行类(Client.java),接口(Interface_Login.java),目标对象(Login.java),代理类(Proxyer.java)。

 

Client.java类的代码

package com.yc.proxy;
/**
 * JDK 动态代理
 * 		
 */
public class Client {
	public static void main(String[] args) {
		Interface_Login login = new Login();	
		//创建被代理对象
		Proxyer proxyer=new Proxyer();
		//创建代理对象
		Interface_Login proxyLogin=(Interface_Login)proxyer.getProxy(login);
		//执行代理方法
		proxyLogin.login("root", "123");
		proxyLogin.login("root", "1234");
		proxyLogin.login("root", "12345");
	}
}

Interface_Login.java接口代码

package com.yc.proxy;

public interface Interface_Login {
	public void login(String user,String pwd );
}

Login.java类的代码

package com.yc.proxy;

public class Login implements Interface_Login{
	//要进行动态增强的方法
	public void login(String user,String pwd ){
		if(user.equals("root") && pwd.equals("123")){
			System.out.println("登录成功");
		}else{
			System.out.println("登录失败");
		}
	}
}

Proxyer.java代理类的代码。(主要:动态代理的代码基本了解与掌控)

最为主要的是对newProxyInstance()方法  与  invoke(Object proxy, Method method, Object[] args)方法的掌控。

package com.yc.proxy;

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

public class Proxyer implements InvocationHandler{
	/**
	 * 目标对象(被代理对象)
	 */
	private Object target;
	/**
	 * 创建代理对象
	 * newProxyInstance(参数一,参数二,参数三)
	 * 		方法参数的含义:
	 * 			参数一:类加载器,被代理对象的类加载器。(一般是固定写法)
	 * 			参数二:字节码数组,被代理对象的接口数组。(一般是固定写法)
	 * 			参数三:一个接口,如何代理。(此处代码只能是谁用谁写)
	 */
	public Object getProxy(Object target){
		this.target=target;
		/**
		 * Proxy是jdk提供的代理对象构建器
		 */
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
									target.getClass().getInterfaces(), //被代理对象的接口数组
									this);}
	/**
	 * 执行被代理对象的任何方法都会经过该方法。(该方法具有拦截的功能)
	 * 		方法参数的含义:
	 * 			Object proxy:代理对象的引用。(一般都不会用到)
	 * 			Method method:执行的方法。
	 * 			Object[] args:执行方法所需要的参数
	 * 返回值(return):当前执行方法的返回值
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object ret=null;
		//获取密码
		String pwd=(String)args[1];
		//但凡密码为“12345” 的用户不能进行登录
		if(pwd.equals("12345")){
			//动态增强(不执行)
			System.out.println("密码为12345的用户拦截成功");
		}else{
			//动态增强(执行方法)
			ret = method.invoke(target, args);
		}
		return ret;
	}
}

最后运行的结果是:

3.CGLIB动态代理

本次项目名【Dynammic_proxy】,CGLIB动态代理包,共有两个类组成,分别为:

执行类(CglibClient.java),目标对象(CglibLogin.java)。

在使用CGLIB前先加入jar包(spring-core-4.3.17.RELEASE.jar   或者  cglib-3.1.jar和asm-3.3.1.jar),本人使用的是第一种,第一种里面也包含了第二种的两个jar包。

CglibClient.java类代码

package com.yc.cglib;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
 * CGLIB动态代理
 *
 */
public class CglibClient {
	public static void main(String[] args) {
		//CGLIB要涉及的类
		Enhancer enhancer=new Enhancer();
		//指定父类
		enhancer.setSuperclass(CglibLogin.class);
		//设置方法回调
		enhancer.setCallback(new MethodInterceptor() {
			CglibLogin login=new CglibLogin();
			/**
			 * 执行被代理对象的任何方法都会经过该方法。(该方法具有拦截的功能)
			 * 		方法参数的含义:
			 * 			前面三个和invoke方法的参数含义和作用都是和“JDK方法的参数含义”一样的
			 * 		返回值(return):当前执行方法的返回值
			 * 	唯一不同的是MethodProxy:当前执行方法的代理对象。(这个也是一般不用的)
			 */
			@Override
			public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
				Object ret=null;
				//获取密码
				String pwd=(String)arg2[1];
				//但凡密码为“12345” 的用户不能进行登录
				if(pwd.equals("12345")){
					//动态增强(不执行)
					System.out.println("CGLIB:密码为12345的用户拦截成功");
				}else{
					//动态增强(执行方法)
					ret = method.invoke(login, arg2);
				}
				return ret;
			}
		});
		//创建代理对象的方法create()
		CglibLogin cglibLogin=(CglibLogin) enhancer.create();
		
		cglibLogin.login("root", "123");
		cglibLogin.login("root", "1234");
		cglibLogin.login("root", "12345");
	}
}

CglibLogin.java类代码

package com.yc.cglib;

public class CglibLogin{
	//要进行动态增强的方法
	public void login(String user,String pwd ){
		if(user.equals("root") && pwd.equals("123")){
			System.out.println("CGLIB登录成功");
		}else{
			System.out.println("CGLIB登录失败");
		}
	}
}

最后运行的结果是:

这是我对JDK与CGLIB动态代理的基本解释,若有不足之处请留言告知,谢谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值