Spring框架(四)AOP之代理模式

本篇介绍一下Spring的AOP模块中关于面向切面的概念。AOP全称Aspect  Oriented Programming,即面向切面编程。第一次听说面向切面编程可能会比较陌生,或者心里堵得慌。这到底是个什么鬼。但是,不要紧,我们不要太去抠字眼,想通过这几个字就想搞明白什么是面向切面,是不太可能的。所以,先不管什么是面向切面,先把这个概念抛掷脑后。先看看下面这个例子:

我有个朋友,自己在家做点蛋糕,然后通过朋友圈卖。送货都是他自己亲自送货。模型如下图:


后来发现这样亲自送货,根本赚不到钱,而且时间都耗费在车上了,因此没有时间去做蛋糕了。这样导致,做得少不敢接太多单,利润都给城市交通了,根本赚不到钱。要解决问题,就需要找一个快递公司专门送货。如是,就有了如下模型了:


看到这里,可能有人会发现,这不就是代理模式吗。确实,这就是代理模式,将原来自己做的事情,交给代理(快递公司)来做,省时省力省钱。

那这代理模式跟AOP有什么关系?代理模式就是AOP的核心原理。面向切面编程可以简单说是面向代理模式编程。所以搞明白什么事代理模式,基本就清楚面向切面是怎么回事了:


接下来,我们通过代码的形式来实现上面的案例:

1、卖家Seller类:

package com.androidxx.proxy;
/**
 * 卖家
 * @author yangjw
 *
 */
public class Seller {
	/**
	 * 卖蛋糕
	 */
	public void sell() {
		System.out.println("做蛋糕");
	}

}


2、快递代理ExpressProxy类:

package com.androidxx.proxy;

public class ExpressProxy {
	
	Seller seller = new Seller();
	
	public void transport() {
		System.out.println("上门收快递");
		seller.sell();
		System.out.println("快递送达");
	}
	
}


3、买家Buyer类:

package com.androidxx.proxy;
/**
 * 买家
 * @author yangjw
 */
public class Buyer {
	
	ExpressProxy express = new ExpressProxy();
	
	public void buy() {
		express.transport();
	}
	
}


4、测试类:

package com.androidxx.proxy;

import static org.junit.Assert.*;

import org.junit.Test;

public class BuyerTest {

	@Test
	public void test() {
		Buyer buyer = new Buyer();
		buyer.buy();
	}

}

以上就是一个静态代理的例子,代理模式就是由一个人代表另一个人完成一项任务。以上例子中就是由快递(ExpressProxy)代表卖家(Seller)去送货给买家(Buyer)。但是,看上面的例子,ExpressProxy为了代理Seller,需要在ExpressProxy类中创建一个Seller对象(被代理的对象);在现实生活中,一个快递公司往往都是可以给任何公司或者组织或者个人送快递的,也就是说现实生活中的快递公司可以是所有人或者组织的代理者。那这样我们岂不是要在ExpressProxy类中创建成千上万个被代理的对象?当然不需要,于是Java推出的动态代理的概念。动态代理就是可以在不修改代理类(ExpressProxy)的情况下,可以给所有对象进行代理。


动态代理

实现动态代理需要了解2个类,分别是InvocationHandler和Proxy,其中InvocationHandler是一个接口,是代理需要实现的接口;Proxy是帮助产生代理实例的一个类。接下来,使用动态代理优化以上案例中的代理模式。

1、首先要定义一个接口SuperSeller:

package com.androidxx.proxy;

public interface SuperSeller {
	public void sell();
}

2、创建Seller类,并实现SuperSeller接口:

package com.androidxx.proxy;
/**
 * 卖家
 * @author yangjw
 *
 */
public class Seller implements SuperSeller {
	/**
	 * 卖蛋糕
	 */
	public void sell() {
		System.out.println("做蛋糕");
	}

}

3、创建动态代理类:

package com.androidxx.proxy;

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

public class DynamicExpressProxy implements InvocationHandler{

	private Object seller;
	
	public DynamicExpressProxy(Object seller) {
		super();
		this.seller = seller;
	}

	/**
	 * 参数1:proxy是代理类的一个对象,但是并不是指代当前的DynamicExpressProxy对象。
	 * 参数2:需要执行的被代理对象的方法
	 * 参数3:需要执行方法的参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("上门收快递");
		//反射原理,执行方法
		//Obj是method方法的返回值
		Object obj = method.invoke(this.seller, args);
		System.out.println("送达快递");
		return obj;
	}
}


4、买家类Buyer:

package com.androidxx.proxy;

import java.lang.reflect.Proxy;

/**
 * 买家
 * @author yangjw
 */
public class Buyer {
	
	public void buy() {
		//被代理的对象
		Object obj = new Seller();
		//被代理对象的Class对象
		Class clss = obj.getClass();
		//通过Proxy产生代理类的实例,此处的proxy对象是代理。
		//动态代理的关键就是此句,动态的创建代理类对象
		SuperSeller proxy = (SuperSeller) Proxy.newProxyInstance(clss.getClassLoader(), clss.getInterfaces(), new DynamicExpressProxy(obj));
		//通过代理执行sell方法
		proxy.sell();
	}
}

5、测试类:

package com.androidxx.proxy;

import static org.junit.Assert.*;

import java.lang.reflect.Proxy;

import org.junit.Test;

public class BuyerTest {
	@Test
	public void test() {
		Buyer buyer = new Buyer();
		buyer.buy();
		
	}
		
}

以上就是使用动态代理的方式来处理卖家--快递--买家的关系。动态代理,顾名思义就是动态的去创建代理。如上代码中Proxy.newProxyInstance就是用于动态创建代理的方法。关于动态代理中的InvocationHandler和Proxy其实很简单,InvocationHandler用于定义一个动态代理的类,Proxy用于产生代理类的实例。

说了半天的代理模式,它跟AOP面向切面有什么关系呢?在开头的时候,已经说了,AOP的核心其实就是代理模式。明白代理模式,在接下来的AOP学习过程中,就容易理解了。大家在学习AOP的时候,其实可以理解为在学习动态代理模式。


Spring 的AOP其实就是一种动态代理模式的实现。


此篇博客为了尽量简化代理模式的说明,有些概念写的可能比较简单,也是为了便于去理解。如果有错误的地方,也欢迎指正。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杨景文Blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值