Spring框架(五)AOP之注解方式

Spring的AOP(面向切面编程、或者叫面向方面编程)一直以来是初学Spring程序员的一个挥之不去的梗,想想当年自己刚开始接触AOP的时候也是一头雾水。我当初的学习方式就是先不管是否理解,既然大家都说好,就先用,用着用着就明白了为什么。本篇文章我也是想尽可能的让大家在学习之初就能明白什么是AOP。AOP的核心其实就是动态代理,这个在第一篇文章【 Spring框架AOP之代理模式】中有讲解,并且此篇文章也会延用上一篇文章的例子,所以如果是初学Spring AOP,可以先去看看【 Spring框架AOP之代理模式】和【 Spring框架之依赖注入】。

我们还是使用上一篇文章的案例,我朋友自己在家做蛋糕,然后再朋友圈卖,一开始都是自己亲自送货。模型如下:
为了节省时间和成本,需要请一个快递公司进行送货,但是又不能破坏现有的商家和买家的关系结构,就需要以面向切面编程(AOP)方式,将快递公司插入卖家和买家中间,如下图:
这样快递公司的加入,并不影响卖家进行蛋糕制作,也不影响买家正常收到货物。卖家和买家不需要修改任何的代码。具体的实现代码如下。
1、首先需要配置Spring的AOP所需的Jar包。将如下jar包导入工程中:
以上Jar文件的下载,可以自行在网上搜索一下。或者在我的“下载资源”中可以 免费下载
2、创建卖家Seller类:
package com.androidxx.proxy;

/**
 * 卖家
 * @author yangjw
 *
 */
public class Seller implements SuperSeller {
	
	public Seller() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * 卖蛋糕
	 */
	public void sell() {
		System.out.println("做蛋糕");
	}

}

3、创建买家Buyer类:
package com.androidxx.proxy;

import java.lang.reflect.Proxy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 买家
 * @author yangjw
 */
//Component注解表示当前类是交由Spring框架管理的一个组件
@Component
public class Buyer {
	
	private SuperSeller seller;
	//Autowired注解表示此方法中的参数seller,需要交由Spring注入。这在Spring的IOC一篇文章中讲过。
	@Autowired
	public void setSeller(SuperSeller seller) {
		this.seller = seller;
	}

	public void buy() {
		seller.sell();
	}
}
以上代码中的注解是 Spring框架IOC中讲到过。不明白的可以先看看【 Spring框架依赖注入】。并且在以上代码中我也写有简单的注释,有点基础的猿,看起来应该并不难理解。
4、创建快递ExpressProxy类:
package com.androidxx.proxy;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

//Aspect注解表示当前类是作为一个"切面"
@Aspect
//Component注解表示将当前类交由Spring进行初始化(管理)
@Component
public class ExpressProxy {
	//Before注解表示在切入点之前执行
	//execution(....)是一种表达式,表示编入点就是sell方法,表示在执行sell方法前,先执行begin方法
	@Before("execution(public void com.androidxx.proxy.Seller.sell())")
	public void begin() {
		System.out.println("上门收快递");
	}
	//After注解表示在切入点之后执行
	@After("execution(public void com.androidxx.proxy.Seller.sell())")
	public void end() {
		System.out.println("快递送达");
	}

}
以上代码中有几个注解是在AOP中特有的,其含义分别如下:
@Aspect:表示此类就是一个切面。换一个说法就是当前类将会被植入某一个切入点之前或者之后,而切入点可能就是一个方法而已。
@Before,@After:定义切入点,分别表示切入点前和后。execution中是一个表达式,写作的形式很多,甚至可以使用通配符。这一点的知识也比较多,此处不做讲解。以上代码的含义可以用一句话说明:
ExpressProxy作为一个切面,切面中有2个切入点,分别是在Seller.sell()方法之前和之后。也就是在执行sell方法之前会先执行begin方法,在执行sell方法之后会执行end方法。
5、创建Spring的配置类:
package com.androidxx.proxy;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

/**
 * 此类是Spring的初始化的入口类,同时也是一个Bean工厂类,提供IOC所需的注入对象
 * @author yangjw
 *
 */
@Configuration //表示此类是一个配置类,作为初始化入口类存在
@EnableAspectJAutoProxy //表示允许使用Aspectj进行AOP的操作
@ComponentScan //表示此类就是一个Bean工厂,在此类中寻找需要的Component
public class BeanFactory {
	
	@Bean //Bean注解表示此方法提供Bean对象,用于IOC的依赖注入
	public SuperSeller provideSeller() {
		return new Seller();
	}

}
6、使用JUnit测试:
package com.androidxx.proxy;

import static org.junit.Assert.*;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BuyerTest {

	@Test
	public void test() {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanFactory.class);
		Buyer buyer = ctx.getBean(Buyer.class);
		buyer.buy();
	}

}
测试结果如下:
上门收快递
做蛋糕
快递送达

AOP的出现的用意就是在不影响原有逻辑的情况下,可以在需要的位置加入一段逻辑。可以看到以上的例子中,没有修改Buyer和Seller的前提下,在sell方法前后加入了一段逻辑代码,这就是AOP的简单运用。

说明:
Spring的核心就是对现有对象的管理,AOP是建立Spring对对象管理的基础之上,要使用Spring的AOP,必须将对象交由Spring管理。所以,本案例中需要建立在IOC的基础上来使用AOP。如果不明白Spring的组织结构的,可以先看看【 Spring的简单介绍】.

【成功是一点点的积累,而积累是需要时间的,不要想着一步登天,抓紧埋头敲代码】


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杨景文Blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值