SPRING AOP的使用

来源:互联网 发布:c语言 变量初始化顺序 编辑:程序博客网 时间:2024/05/17 22:56

Spring 作为现在最主流的框架,其IoCAOP为所有开发都提供了非常方便及简单的开发体验。但是很多新手在Spring的使用中,只使用的Spring最基本的IoC功能,其核心的AOP涉及很少。这样就造成了很多人在编写代码时和以前不用框架一样,只是省去了常用的setget方法。并没有直接用到Spring的核心功能。因此我在这里针对Spring AOP做一个简单的介绍,可以让大家领略Spring AOP的魅力。

先简单说一上什么是AOPAOPAspect Oriented Programming(面向切面编程)。可以应该都知道AOP是面向切面编程,可如何面向切面编程。什么叫切面,可能许多新人一知半解。

在这里我举一个例子。假设我们开发了一套商城的程序,程序有这么一个功能,用户查询相关的商品,展示相关商品的价格信息,可以点击商品进行购买,形成订单信息。程序结构是这样的,Controll负责接收用户请求返回数据,Service负责根据Controll传来数据进行查询数据库相关的商品。Mapper负责进行查询。程序正常运行,可双十一到了,我们对所有购买超过1000元的订单进行满100050的优惠。但是在项目开发前期的时候并没有考虑到,因此系统中并没有这个功能,而又不能对已有的商品进行调价。在这种情况下我们可以考虑我们就可以考虑到用AOP了。AOP可以对系统中所有的方法执行前、执行后进行切入。然后执行我们新增加的部分功能。在这里我们可以编写一个优惠的程序,然后在调用之前进行切入,形成新的订单数据。这样我们在不改变原有代码结构的基础上就可以实现了。另外当某个系统我们没有源码,又想增加新的功能时也可以考虑用这种方法。

在具体说明AOP使用前,我们需要先了解几个AOP的术语。

Advice(通知)通知定义了切面什么时候使用。即方法之前还是之后使用或者是抛出异常时。因此通知定义了五种状态分别是:Before方法调用之前执行;After方法调用之后执行,无论方法是否执行成功;After-returning在方法执行成功之后执行;After-throwing在方法抛出异常之后执行;Around包裹了被通知的方法,可以显示的调用相关的方法,定义方法执行前、后需要执行的操作。

Joinpoint(连接点)是在应用执行过程中能够插入切面的一个点。通俗点说就是我们在定义一个方法后,如果这个方法为切点,可以通过连接点这个对象中取得切入的原始对象、方法名、参数列表等信息。我们可以通过连接点来改变原始对象中的某些数据。

Pointcut(切点)定义了执行过程中从如果切入。和通知一起使用。通知定义了何时,而切点就是定义了何处。切点就是一系列的规格,对满足规则的方法进行切入。这个规则称之为AspectJ切点指示器。我们常用的切点指示器有execution()匹配连接点的执行方法;@annotation匹配带有指定的注解;arg()匹配参数为指定类型的执行方法;@args()匹配参数由指定注解标注的执行方法;this()匹配AOP代理的Bean引用为指定类型的类;target()匹配目标对象为指定类型的类;@target()匹配特定的执行对象,这些对象对应的类要具备指定类型的注解;within()匹配指定的类型;@within()指定注解所标注的类型;

Aspect(切面)定义了切通知和切点的所有集合。通俗点说就是定义当前类为一个AOP切面类,里面包含了AOP相关的配置。需要对里面的切点或通知等信息进行解析。

Introduction(引入)引入允许我们向现有的类中添加新的方法或属性。假设类A实现了接口Imp,后来需要有了变化,我们新建了接口Test,我们需要类A也要实现Test接口,但A已经在其他地方使用,直接进行改变会影响其他地方的使用,我们就可以通过引入在不改变原有代码的基础上增加新的接口实现。

通过上面对相关术语的介绍我们大体了解了AOP的大体结构。下面我们通过具体的例子来说明一个AOP的使用。使大家有一个更清晰的认识。

 

1、首先定义接口类

public interface DisposeInter {

 

public void insert(Stringjson);

}

 

2、接口实现

@Service

public class DisposeImplimplements DisposeInter {

 

@Override

public void insert(Stringjson) {

System.out.println(json+"记录订单信息");

}

 

}

3、调用相关方法

 

@Controller

public class TestController {

@Autowired

private DisposeInterinter;

public void test() {

inter.insert("订单001");

}

}

 

4、当需要增加新的功能时,定义切面

 

@Component

@Aspect

@EnableAspectJAutoProxy

public class AspectTest {

 

@Before("execution(* com.qlys.logistics.order.controller.DisposeImpl.insert(*))")

public void before(JoinPointpoint) {

System.out.println("方法执行前切入 参数=" +point.getArgs()[0]);

point.getArgs()[0] ="订单002记录订单信息  参数值改变";

System.out.println("改变参数值");

 

System.out.println("*************************执行前切入完成************************");

}

 

@After("execution(* com.qlys.logistics.order.controller.DisposeImpl.insert(*))")

public void after(JoinPointpoint) {

System.out.println("***************************方法执行后切入***********************");

System.out.println("方法执行后切入 参数=" +point.getArgs()[0]);

System.out.println(point.getTarget().getClass() +"类  " + point.getSignature().getName() +"方法");

}

 

 

}

 

5、测试

 

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {"classpath:application-core.xml","classpath:spring-base.xml" })

public class TestMain {

 

@Autowired

private TestControllercon;

@Test

public void show() {

con.test();

}

}

 

信息显示: