String框架 AOP面向切面编程

本文详细介绍了Spring框架中AOP(面向切面编程)的三种配置方法:XML配置、注解配置和使用config.java启用。通过实例展示了如何在方法执行前后插入额外操作,实现非侵入式的功能增强,同时保持主要业务逻辑的清晰。涉及到的组件包括AspectJ、Bean配置以及不同类型的Advice。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在竖向处理过程中,插入独立的处理。
使得2种处理同时进行,不破坏主处理
以方法为单位

  • 在某些方法开始时候,自动插入一些操作
    在这里插入图片描述
    创建工程 spring Maven 做个例子

  • 首先需要配置pom.xml

通过此标签实现AOP的基本功能
在这里插入图片描述
Aspectj: AOP的具体实装framework ,Eclipse Foundation的工程都有

方法1(使用xml配置bean aop:config)

在Bean类中调用addData方法时,会自动调用addDataBefore方法

  • 创建Bean,和接口类
package jp.tuyano.spring.aop1;

public interface IMyBean<T> {
	public void setDataObject(T obj);
	public T getDataObject();
	public void addData(Object obj);
	public String toString();
}

package jp.tuyano.spring.aop1;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class MyBean1 implements IMyBean<List<String>> {
	private List<String> data = new ArrayList<String>();
	private Date date = Calendar.getInstance().getTime();

	@Override
	public void setDataObject(List<String> obj) {
		data = obj;
	}
	
	@Override
	public List<String> getDataObject() {
		return data;
	}
	
	@Override
	public void addData(Object obj) {
		data.add(obj.toString());
	}

	@Override
	public String toString() {
		String result = "MyBean1 [data=";
		for(String s : data){
			result += s + ", ";
		}
		SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd");
		result += "date=" + fm.format(date) + "]";
		return result;
	}

}

  • 创建MyBeanAspect
    在addData方法调用时,会自动调用此方法
package jp.tuyano.spring.aop1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

public class MyBeanAspect {

	public void addDataBefore(JoinPoint joinPoint) {
		System.out.println("*addData before...*");
		String args = "args: \"";
		for(Object ob : joinPoint.getArgs()){
			args += ob + "\" ";
		}
		System.out.println(args);
	}
}


  • 创建bean.xml,配置bean
    aop:aspect ref指定被插入方法的id
    aop:pointcut ポイントカカっと设置插入点 expression 当~方法执行时(过滤条件),设置插入点id
    aop:アドバイス 设置在执行方法的什么时候插入aspect方法,比如:
    aop:before 设置插入方法设置在before, method为addDataBefore,插入点为上面设置的id
    在这里插入图片描述
<?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/aop 
		http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context.xsd">

	<aop:config>
		<aop:aspect id="mybeanaspect1" ref="aop1">
			<aop:pointcut expression="execution(* jp.tuyano.spring.aop1.IMyBean.addData(..))" id="p1"/>
			<aop:before method="addDataBefore" pointcut-ref="p1"/>
		</aop:aspect>
	</aop:config>
	
	<bean id="bean1" class="jp.tuyano.spring.aop1.MyBean1"></bean>
	<bean id="aop1"  class="jp.tuyano.spring.aop1.MyBeanAspect"></bean>

</beans>

  • 主函数

在主函数中调用2次addData方法,

	public static void main(String[] args) {
		app = new ClassPathXmlApplicationContext("bean.xml");
		IMyBean<String> bean = (IMyBean<String>) app.getBean("bean1");
		bean.addData("Hello AOP World!");
		bean.addData("this is sample data.");
		System.out.println(bean);
	}

方法2(使用<aop:aspectj-autoproxy/>配置)

  • 重写MyBeanAspec
package jp.tuyano.spring.aop1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyBeanAspect {

	// 指定插入点 ,且指定在方法addData执行之前插入
	@Before("execution(* jp.tuyano.spring.aop1.IMyBean.addData(..))")
	public void addDataBefore(JoinPoint joinPoint) {
		System.out.println("*addData before...*");
		String args = "args: \"";
		for(Object ob : joinPoint.getArgs()){
			args += ob + "\" ";
		}
		System.out.println(args);
	}
}

在这里插入代码片
  • bean.xml 重写
	<aop:aspectj-autoproxy/>
	<bean id="bean1" class="jp.tuyano.spring.aop1.MyBean1"></bean>
	<bean id="aop1"  class="jp.tuyano.spring.aop1.MyBeanAspect"></bean>

  • 主函数 和方法一一样
	public static void main(String[] args) {
		app = new ClassPathXmlApplicationContext("bean.xml");
		IMyBean<String> bean = (IMyBean<String>) app.getBean("bean1");
		bean.addData("Hello AOP World!");
		bean.addData("this is sample data.");
		System.out.println(bean);
	}

方法3 (使用config.java配置 @EnableAspectJAutoProxy )

  • 删除bean.xml
  • 定义config.java
    @EnableAspectJAutoProxy
package jp.tuyano.spring.aop1;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy  
public class MyBeanConfig {

	@Bean
	public MyBean1 bean1() {
		return new MyBean1();
	}
	
	@Bean
	public MyBeanAspect aop1() {
		return new MyBeanAspect();
	}
}

  • 配置的事情也在aspect.java里做
package jp.tuyano.spring.aop1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyBeanAspect {

	@Before("execution(* jp.tuyano.spring.aop1.IMyBean.addData(..))")
	public void addDataBefore(JoinPoint joinPoint) {
		System.out.println("*addData before...*");
		String args = "args: \"";
		for(Object ob : joinPoint.getArgs()){
			args += ob + "\" ";
		}
		System.out.println(args);
	}
}


  • 主函数配置修改
	public static void main(String[] args) {
		app = new AnnotationConfigApplicationContext(MyBeanConfig.class);
		IMyBean<String> bean = (IMyBean<String>) app.getBean("bean1");
		bean.addData("Hello AOP World!");
		bean.addData("this is sample data.");
		System.out.println(bean);
	}
	

アドバイス

@AfterReturning
@AfterThrowing
@Around after+before都拦截到,必须手动启动被拦截方法。
@Before

package jp.tuyano.spring.aop1;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyBeanAspect {

	@AfterReturning(value="execution(* jp.tuyano.spring.aop1.IMyBean.toString())", returning="str")
	public void toStringAfterReturning(String str) {
		System.out.println("*toString returning...*");
		System.out.println("return:" + str);
		System.out.println("*...end toString returning*");
	}
	
	@AfterThrowing(value="execution(* jp.tuyano.spring.aop1.MyBean2.addData(..))", throwing="e")
	public void addDataAfterThrowing(Exception e) {
		System.out.println("*Except in addData...*");
		System.out.println(e.getLocalizedMessage());
		System.out.println("*...end Except in addData*");
	}
	
	@Around("execution(* jp.tuyano.spring.aop1.MyBean1.addData(..))")
	public void toStringAround(ProceedingJoinPoint joinPoint) {
		System.out.println("*around addData...*");
		System.out.println("before:" + joinPoint.getTarget());
		try {
			joinPoint.proceed(); // 必须要指定启动被拦截的方法
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("after:" + joinPoint.getTarget());
		System.out.println("*...end around addData.*");
	}
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值