JDK动态代理

动态代理

我们还未学习面向切面编程时,总是把某些方法在业务逻辑中调用,例如权限检查,记录日志等;这样做会导致后期维护时会有些混乱;因此我们需要采用AOP面向切面编程;将权限检查,记录日志等方法称为增强,并放在切面类中,再创建代理对象,对目标对象进行处理,使之附上之前约定的那些增强方法;

JDK动态代理

JDK动态代理的步骤如下:

  1. 创建接口UserDao,接口实现类UserDaoImpl,切面类MyAspect,JDK代理类jdkProxy(实现InvocationHandler接口)(也可以成为实现invocationHandler的类,因为这个类中invocationHandler的invoke方法起到了关键作用)
  2. 在JDK代理类中创建代理方法createProxy,使用java.lang.reflect包中的Proxy代理类的静态方法Proxy.newProxyInstance(类加载器,被代理对象实现的所有接口,实现InvocationHandler的类)返回一个代理类实例(因此真正起作用的是Proxy类,JDK代理类的作用其实是将被代理对象的接口放进去)
  3. 由因为Proxy.newProxyInstance方法返回一个Object,可以强制类型转换为真实对象的接口UserDao,此时UserDao不再是一个普通的UserDao,而是当它执行方法时,会先调用JDK代理类jdkProxy中实现的invoke方法,并且将被代理的对象,要执行的方法和参数反射填入invoke方法的参数中;
  4. 而在invoke方法中,我们需要声明一个切面,用于使用增强方法。在真实对象调用方法的前后,我们可以添加增强方法

JdkProxy类

package com.itheima.jdk;

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

import com.itheima.aspect.MyAspect;

public class JdkProxy implements InvocationHandler {

	// 声明目标类接口
	private UserDao userDao;

	// 创建代理方法
	public Object createProxy(UserDao userDao) {
		this.userDao = userDao;
		// 1.类加载器
		ClassLoader classLoader = JdkProxy.class.getClassLoader();
		// 2.被代理对象实现的所有接口
		Class<?>[] clazz = userDao.getClass().getInterfaces();
		// 3.使用代理类,进行增强,返回的是代理后的对象;
		// 返回代理类的一个实例,返回后的代理类可以当作被代理类Proxy使用
		return Proxy.newProxyInstance(classLoader, clazz, this);
	}

	// 所有动态代理类Proxy的方法调用都交给下面这个重写的invoke()执行
	// proxy 被代理的对象
	// method 测试类中动态调用方法时,反射将要被执行的方法信息
	// args 反射回来的,执行方法时需要的参数
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// 声明一个切面,用于使用增强方法
		MyAspect myAspect = new MyAspect();
		// 前增强,即在调用程序本身方法之前,使用增强方法
		myAspect.check_Permissions();

		/*
		 * 根据反射,动态调用程序本身方法 此时用userDao是因为这样可以降低耦合度,即修改代码的难度。
		 * userDao是接口类,接口类可以引用实现类对象,因此这样无论实现类是谁,都不需要修改这里的代码 体现了面向接口编程的思想
		 *
		 **/
		method.invoke(userDao, args);

		// 后增强
		myAspect.log();
		return null;
	}

}

测试类

package com.itheima.jdk;

public class JdkTest {

	public static void main(String[] args) {
		// 创建代理对象
		JdkProxy jdkProxy = new JdkProxy();
		// 创建目标类
		UserDao userDao = new UserDaoImpl();
		// 从代理对象中获取被增强后的目标对象
		UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);

		// 执行方法
		userDao1.addUser();
		userDao1.deleteUser();

	}

}

执行结果
在这里插入图片描述

若使用普通的,没被代理过的对象userDao,则执行结果是
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值