初识Java JDK动态代理(AOP)

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

1、什么是代理

当一个对象不能直接使用,可以在客户端和目标对象中间创建一个中介,这个中介就是代理。

2、代理的作用

  1. 控制访问:代理中,控制是否调用目标对象的方法
  2. 功能增强:代理类在完成目标类的调用后,附加一些功能,这些额外功能就是功能增强

3、代理的实现方式

1、静态代理

1. 实现:手写代理类,同时目标类是规定的
2. 优点:易理解,易使用
3. 缺点:会产生大量代理类;接口改变时,影响大量代理类

/*静态代理的创建步骤
   1、创建目标类(厂家)与代理类(商家)的接口(封装了厂家与商家共同实现的功能)
   	public interface Sell{float sell(amount);}
   2、创建目标类,实现1中的接口
   	public class Factory implements Sell{
   		public float sell(int amount){
   			return 80.0f;
   		}
   	}
   3、创建代理类,实现1中接口同时调用目标类中的方法
   	调用目标类中的方法目的是为了完成用户期望的功能(不向厂家拿货,怎么卖给客户)
   	public class Merchantimplements Sell{
   		public float sell(int amount){
   			Factory f =new Factory();
   			float price =f.sell(amount);
   			price += 25;
   			return price;
   		}
   	}
   4、创建客户端,调用代理类的方法
   	Sell m =new Merchant();
   	float price =m.sell(1);
*/

static_proxy
2、动态代理

1. 实现:动态代理是创建Java对象的一种能力,创建的代理类是活动的

  • JDK动态代理:使用JDK java反射包中的接口和类实现动态代理的功能。反射包:java.lang,reflect,里面有三个类:InvocationHandler、Method、Proxy
  • cglib动态代理:cglib是第三方库,通过继承目标类并重写目标类方法,实现功能修改;要求目标不能被final修饰。

2. 优点:不用创建代理类;代理类是活动的,对不同目标类可随时创建代理,可设置的

/*动态代理的创建步骤
	1、创建目标类(厂家)实现的接口(封装了厂家实现的功能)
		public interface Sell{float sell(amount);}
	2、创建目标类,实现1中的接口	
		调用目标类中的方法目的是为了完成用户期望的功能(不向厂家拿货,怎么卖给客户)
		public class Factory implements Sell{
			public float sell(int amount){
				return 80.0f;
			}
		}
	3、创建InvocationHandler接口的实现类,在invoke方法中写人代理类的功能操作
		调用目标类方法
		功能增强
		public class SellHandler implements InvocationHandler{
			private Object obj =null;
			//从外界传入代理目标对象
			public SellHandler(Object obj){
				this.obj =obj;
			}
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
				Object res =null;
				//执行目标类方法
				res =method.invoke(obj,args);
				//功能增强
				if(res!=null){
					float price =(float)res;
					price += 25;
					res =price;
				}
				return res;
			}
		}
	4、通过Proxy类的静态方法,创建代理类对象,把返回值转变为目标类实现接口的类型
		//创建目标类对象(第二步)
		Factory f =new Factory();
		//创建InvocationHandler接口的实现类(第三步)
		InvocationHandler h = new SellHandler(f);
		//创建代理对象(第四步)
		Sell proxy=(Sell)Proxy.newProxyInstance(
			s.getClass().getClassLoader(),
			s.getClass().getInterface(),
			h);
		//最后,调用接口中的方法
		float price =proxy.sell(1);
*/

在这里插入图片描述

4、java.lang,reflect中的InvocationHandler(接口)、Method、Proxy

1、Method类(表示方法,目标类中的方法)

//Method类中的invoke底层是实现了接口sun.reflect.MethodAccessor中的invoke方法
public interface MethodAccessor {
    Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException;
}
public void doMethod() throw Exception{
	HelloService target =new HelloServiceImpl();
	//Method[] method =HelloService.class.getMethods();
	//获取目标类中的方法
	Method method =HelloService.class.getMethod("方法名",String.class);
	/*
		invoke是Method类中的一个方法,表示执行这个对象方法
		参数:
			Object obj        执行的对象
			Object...args     方法执行的参数值
		返回值:
			Object            方法执行后返回值类型(getMethod中使用的方法返回类型)
	*/
	Object obj =method.invoke(target,"参数");//目标类方法调用
	/*等价于静态代理中第三步代理类实现目标类方法
	float price = factory.sell(amunot);
	factory是目标类
	sell是目标类中的方法(重写于接口)
	*/
}

2、InvocationHandler接口(调用处理器)

/*InvocationHandler接口下的唯一方法invoke,
	表示代理对象要执行的功能代码,代理类想实现的操作写在该方法里面
		代理类完成的功能:
			调用目标类:执行目标类的方法
			功能增强:在目标类调用时增强功能
	方法原型:
		Object proxy     jdk创建的代理对象,jdk自动赋值
		Method method    目标类中的方法,jdk提供
		Object[] args    目标类中的方法参数,jdk提供
	使用步骤:
		1、实现InvocationHandler接口
		2、重写invoke方法,写入对代理对象实现功能的操作(代理类对目标类的操作)
*/
public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

3、proxy类(核心对象,用于创建代理对象)

/*创建代理对象
	使用Proxy类的静态方法:newProxyInstance
		等价于静态代理中第三步创建代理类
		TaoBao tb =new TaoBao();
	newProxyInstance参数列表:
		ClassLoader loader      类加载器,负责向内存中加载对象,使用反射拿取对象的ClassLoader类a(a.getClass().getClassLoader(),目标对象的类加载器)
		Class<?>[] interfaces   接口,目标类实现的接口,反射获取
		InvocationHandler h     调用处理器,编写代理类要完成的功能
		return Object           目标对象的代理对象
*/
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{}

5、总结

1、什么是动态代理?其中动态是什么?

  1. 动态代理:是使用jdk的反射机制去创建对象的能力,创建的是代理类对象,不用你手动创建类文件
  2. 动态:在程序执行时,调用jdk提供的方法创建代理类对象

2、动态代理执行流程

/*
在下面例子中:
	当执行sell方法时,先创建代理对象proxy再执行方法sell,
	执行前将要执行的操作:
		通过反射获取类加载器
		通过反射获取目标对象的接口
		要代理的目标对象f通过new获取,创建InvocationHandler实例时传入h
		h中的invoke通过jdk一系列操作后获得proxy(创建的代理对象),method(执行的方法),args(方法的参数)
		执行h中invoke的操作:
			实现目标类方法:method.invoke(目标类对象,args);
			增强功能
		方法执行完,返回结果

注意:代理对象proxy的类型为com.sun.proxy.$proxy0
*/
Factory f =new Factory();
InvocationHandler h = new SellHandler(f);
Sell proxy=(Sell)Proxy.newProxyInstance(
	f.getClass().getClassLoader(),
	f.getClass().getInterface(),
	h);
float price =proxy.sell(1);

3、动态代理可以做什么
在不改变原理目标方法的前提下,可以在代理中实现增加功能。
假如你用别人给你的一个方法getFun,在Fun.class 中,Fun fun =new Fun(); fun.getFun(); 现在这个方法还可以用但少了功能,这时你就可以以这个class文件为目标对象,创建代理对象,实现功能增强。(jdk动态代理目标类是必需要实现接口的)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝桉未与

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值