定义一个接口
package com.atChina.Test;
public interface SomeService {
public void doSome();
}
定义接口的实现类
package com.atChina.Test;
public class SomeServiceImpl implements SomeService {
@Override
public void doSome() {
System.out.println("执行了doSome业务方法...");
}
}
定义一个切面类
package com.atChina.Test;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* @Aspect:来自aspectj框架,表示当前类是切面类
* 切面类是用来给业务方法增强功能的类
*/
@Aspect
public class MyAspect {
/**
* @Before:前置通知
* 属性:value,表示切入点表达式(切面功能加入的位置)
* 位置:在方法的上面
*
* 特点:
* 1.在目标方法之前先执行
* 2.不能改变目标方法的执行结果
* 3.不会影响目标方法的执行
*/
@Before(value="execution(* com.atChina.Test.SomeServiceImpl.doSome())")
public void beforeFunc(){
System.out.println("前置通知:在目标方法之前,实现日志功能");
}
}
定义配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引用Spring的多个Schema空间的格式定义文件 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd ">
<!-- 声明目标类对象 -->
<bean id="someService" class="com.atChina.Test.SomeServiceImpl" />
<!-- 声明切面类对象 -->
<bean id="myAspect" class="com.atChina.Test.MyAspect" />
<!-- 声明自动代理生成器,创建代理对象 -->
<aop:aspectj-autoproxy /> <!-- 寻找aspectj框架能够识别的标签 -->
</beans>
定义测试方法
@Test
public void test1(){
String configLocation = "com/atChina/Test/applicationContext.xml"; // 类路径的根目录
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
// 目标对象有接口,aspectj默认使用的是jdk动态代理
SomeService proxy = (SomeService) ctx.getBean("someService");
System.out.println(proxy.getClass().getName());
proxy.doSome();
}
执行结果:
前置通知方法可以有参数
package com.atChina.Test;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* @Aspect:来自aspectj框架,表示当前类是切面类
* 切面类是用来给业务方法增强功能的类
*/
@Aspect
public class MyAspect {
/**
* @Before:前置通知
* 属性:value,表示切入点表达式(切面功能加入的位置)
* 位置:在方法的上面
*
* 特点:
* 1.在目标方法之前先执行
* 2.不能改变目标方法的执行结果
* 3.不会影响目标方法的执行
*
* 前置通知方法可以有参数
* JoinPoint连接点,是一个方法,表示切入点表达式中每一个方法
*/
@Before(value="execution(* *..SomeServiceImpl.do*(..))")
public void beforeFunc(JoinPoint jp){
System.out.println(jp.getSignature()); // 连接点的方法签名
Object[] args = jp.getArgs(); // 获取参数数组
System.out.println(args.length);
System.out.println(args[0]); // 获取具体参数值
System.out.println("前置通知:在目标方法之前,实现日志功能");
}
}