Spring AOP(面向切面示例)

本文内容纲要:

- 使用XML配置的方法:

-

- 使用注解的方法:

什么是AOP?

基本概念

切面(aspect):横切关注点被模块化的特殊对象。

通知(advice):切面必须要完成的工作。切面中的每个方向称之为通知。通知是在切面对象中的。

目标(target):被通知的对象。

代理(proxy):向目标对象应用通知后创建的对象。

连接点(joinpoint):目标对象的程序执行的某个特定位置。如某个方法调用前,调用后的位置。包括两个信息:1.目标程序的哪个方法?2.方法执行

前还是执行后?

切点(pointcut):每个类会有多个连接点,AOP通过切点定位到特定的边接点。

类比,连接点相当于数所成方圆 中的记录,而切点相当于查询条件。一个切点匹配多个连接点。

使用XML配置的方法:

1.导入 spring包和aspectj的两个jar包

Image

2.目标对象(要切入的对象)

首先为了不违反开闭原则和更好的可扩展性,目标对象实际上是实现了已定义好的某个接口

接口:

package com.itnba.test;

public interface IHuman {

public void chifan();

public void shuijiao();

}

实现接口的两个类:

package com.itnba.test;

import org.springframework.stereotype.Component;

public class Chinese implements IHuman {

@Override

public void chifan() {

// TODO 自动生成的方法存根

System.out.println("中国人吃饭");

}

@Override

public void shuijiao() {

// TODO 自动生成的方法存根

System.out.println("中国人睡觉");

}

}

package com.itnba.test;

import org.springframework.stereotype.Component;

public class American implements IHuman {

@Override

public void chifan() {

// TODO 自动生成的方法存根

System.out.println("美国人吃饭");

}

@Override

public void shuijiao() {

// TODO 自动生成的方法存根

System.out.println("美国人睡觉");

}

}

3.定义一个切面类

package com.itnba.test;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.stereotype.Component;

public class Qiemian {

public void chifanqian(){

System.out.println("洗手");

}

public void chifanhou(){

System.out.println("漱口");

}

public void shuijiaoqian(){

System.out.println("洗澡");

}

}

4.XML文件配置

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-4.3.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"

default-autowire="byName"

>

<!-- 首相要实例化目标对象类和切面类 -->

<bean id="chinese" class="com.itnba.test.Chinese"></bean>

<bean id="american" class="com.itnba.test.American"></bean>

<bean id="qiemian" class="com.itnba.test.Qiemian"></bean>

<aop:config>

<!-- 要切入的对象 -->

<aop:pointcut expression="execution(* com.itnba.test.*.chifan(..))" id="chifan"/>

<aop:pointcut expression="execution(* com.itnba.test.*.shijiao(..))" id="shijiao"/>

<!-- 切入点 -->

<aop:aspect id="ha" ref="qiemian"><!-- 切面类 -->

<!-- <aop:之前before、之后after... method="切面类中的方法" pointcut-ref="上面的切入的对象"/> -->

<aop:before method="chifanqian()" pointcut-ref="chifan"/><!-- 之前通知 -->

<aop:after method="chifanhou()()" pointcut-ref="chifan"/><!-- 之后通知 -->

<aop:before method="shuijiaoqian()" pointcut-ref="shijiao"/>

</aop:aspect>

</aop:config>

</beans>

5.运行

package com.itnba.test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

//要用接口接收

IHuman c= (IHuman)context.getBean("chinese");

c.chifan();

c.shuijiao();

System.out.println("*********************************");

//要用接口接收

IHuman a= (IHuman) context.getBean("american");

a.chifan();

a.shuijiao();

}

}

结果:

Image

使用注解的方法:

1.导如 spring包和aspectj的两个jar包

Image

2.配置文件中加入aop命名空间

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-4.3.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-4.3.xsd" >

<!-- 自动扫描包下的类,并将其实例化。多个包之间用,隔开 -->

<context:component-scan base-package="com.itnba.test"></context:component-scan>

<!-- 配置文件中启动AspectJ的注解功能 ,默认是false,要将其改为true -->

<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

</beans>

3.目标对象(要切入的对象)

首先为了不违反开闭原则和更好的可扩展性,目标对象实际上是实现了已定义好的某个接口

接口:

package com.itnba.test;

public interface IHuman {

public void chifan();

public void shuijiao();

}

实现接口的两个类:

package com.itnba.test;

import org.springframework.stereotype.Component;

@Component

public class Chinese implements IHuman {

@Override

public void chifan() {

// TODO 自动生成的方法存根

System.out.println("中国人吃饭");

}

@Override

public void shuijiao() {

// TODO 自动生成的方法存根

System.out.println("中国人睡觉");

}

}

package com.itnba.test;

import org.springframework.stereotype.Component;

@Component

public class American implements IHuman {

@Override

public void chifan() {

// TODO 自动生成的方法存根

System.out.println("美国人吃饭");

}

@Override

public void shuijiao() {

// TODO 自动生成的方法存根

System.out.println("美国人睡觉");

}

}

4.定义一个切面类,直接在里面注解

package com.itnba.test;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.stereotype.Component;

@Aspect //声明该类是切面类

@Component//配置文件中启动自动扫描功能

public class Qiemian {

@Before("execution(* com.itnba.test.*.chifan(..))")//在那个方法的之前通知 *代表全部..代表所有形参,不管有多少

public void chifanqian(){

System.out.println("洗手");

}

@After("execution(* com.itnba.test.*.chifan(..))")//在那个方法之后通知

public void chifanhou(){

System.out.println("漱口");

}

@Before("execution(* com.itnba.test.*.shuijiao(..))")

public void shuijiaoqian(){

System.out.println("洗澡");

}

}

5.写好后用main函数来运行一下

package com.itnba.test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

Chinese c= context.getBean(Chinese.class);

c.chifan();

c.shuijiao();

System.out.println("*********************************");

American a= (American) context.getBean("american");

a.chifan();

a.shuijiao();

}

}

结果:

Image

这样,Spring的面向切面编程就简单介绍完了。

通知分类:

前置通知(@Before) -- 在目标方法执行前执行的通知。

后置通知(@After) -- 在目标方法执行后执行的通知。无论是否发生异常。后置通知中,无法读取目标方法返回的结果。

返回通知(@AfterReturnning) --在目标方法执行成功后执行的通知。在返回通知中可以访问目标返回结果的。

@AfterReturnning(value="execution(* com.itnba..*(..))",returning="result")

public void afterRun(Object result){

System.out.println(result);

}

异常通知(@AfterThrowing) -- 在目标方法执行出错后执行的通知。

@AfterThrowing(value="execution(* com.itnba..*(..))",throwing="ex")

public void afterThrowing(Exception ex){

System.out.println(ex.getMessage());

}

环绕通知(@Around) -- 需要切面方法携带ProceedingJoinPoion参数,类似于一个完整的动态代理,环绕通知必须要有一个返回值,是目标方法的返

回值。

@Around("execution(* com.itnba..*(..))")

public object aroundAdvice( ProceedingJoinPoint pjp){

object obj = null;

try{

//做前置通知

obj = pjp.proceed();

//做返回通知

}

catch(Exception ex){

//做异常通知

}

//做后置通知

return obj;

}

添加日志:

切面方法可以加入参数(JoinPoint) joinPost.getSignature().getXXX()获得相关方法信息

切面方法中可以加入Object参数,用来获得目标方法的返回值(只对返回通知起作用)

本文内容总结:使用XML配置的方法:,,使用注解的方法:,

原文链接:https://www.cnblogs.com/hq233/p/6637488.html

以上是 Spring AOP(面向切面示例) 的全部内容, 来源链接: utcz.com/z/296861.html

回到顶部