在竖向处理过程中,插入独立的处理。
使得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.*");
}
}