AOP底层-JDK动态代理

9 篇文章 0 订阅
1 篇文章 0 订阅
需求:CustomerService业务类,有save,update方法,希望在save,update方法执行之前记录日志。

接下来使用JDK动态代理实现

1.UserService接口
package com.zslaa.service;
public interface UserService {
	public void save();
	public void update();
}
2.UserServiceImpl实现
package com.yiidian.service.impl;

import com.zslaa.service.UserService;
public class UserServiceImpl implements UserService {

	@Override
	public void save() {
		System.out.println("执行save方法");
	}

	@Override
	public void update() {
		System.out.println("执行update方法");
	}

}
3.编写JDK动态代理工具类(该工具类,专门用于生成某个接口实现类(目标对象)的代理对象)
package com.zslaa.proxy;

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

public class JDKProxyUtils {

	/**
	 * 使用JDK动态代理获取代理对象
	 * target: 目标对象
	 * @return
	 */
	public static Object getProxy(final Object target){
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(),    // 和目标对象一样的类加载器
				target.getClass().getInterfaces(), // 目标对象的接口列表
				new InvocationHandler() {
					
					//invoke: 这个方法在每次调用代理类对象的时候被执行啦!!!
					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						System.out.println("记录日志");
						
						//调用目标对象的方法
						return method.invoke(target, args);
					}
				});
	}
}
4.编写测试类
package com.zslaa.test;
import org.junit.Test;
import com.yiidian.proxy.JDKProxyUtils;
import com.yiidian.service.UserService;
import com.yiidian.service.impl.UserServiceImpl;

public class Demo1 {
	
	@Test
	public void test1(){
		//目标对象
		UserService service = new UserServiceImpl();
		//获取JDK动态代理对象(接口代理)
		UserService proxy = (UserService)JDKProxyUtils.getProxy(service);
		//调用代理对象
		proxy.save();
		proxy.update();
	}
	
}
5.运行结果(分析)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210316135514383.png#pic_center)

分析:从运行结果看出,UserService的save和update方法都成功在执行之前,切入了日志代码。

案例分析

上面代码中,Proxy类的静态方法newProxyInstance()方法生成了一个对象,这个对象实现了CustomerService中指定的接口。返回值是CustomerService接口的实现类。

动态代理就是在运行时生成一个类,这个类会实现你指定的一组接口,而这个类没有.java文件,是在运行时生成的,你也不用去关心它是什么类型的,你只需要知道它实现了哪些接口即可。
newProxyInstance()方法的参数
Proxy类的newInstance()方法有三个参数:
1、ClassLoader loader:它是类加载器类型,CustomerService.class.getClassLoader()就可以获取到ClassLoader对象,只要你有一个Class对象就可以获取到ClassLoader对象;

2、Class[] interfaces:指定newProxyInstance()方法返回的对象要实现哪些接口,没错,可以指定多个接口,例如上面例子只我们只指定了一个接口:Class[] cs = {CustomerService.class};

3、InvocationHandler h:它是最重要的一个参数!它是一个接口!它的名字叫调用处理器!上面例子中proxy代理对象是CustomerService接口的实现类对象,那么它可以调用save()和update()方法,其实无论你调用代理对象的什么方法,它都是在调用InvocationHandler的invoke()方法!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值