点击这查看:aop的基本概念
aspectJ实现的基本步骤
- 创建maven项目
- 加入依赖
1)spring
2) asepectJ依赖 - 创建目标类:接口和它的实现类
- 创建切面类:普通类
1)在类的上面加入 @Aspect
2)在类中定义方法,方法就是切面的功能代码
在方法的上面加入aspectJ的通知注解,例如@Before
还需要指定切入点表达式 execution() - 创建spring的配置文件:声明对象,把配置的交给容器统一管理
1)声明目标对象
2)声明切面对象
3)声明aspectJ框架中的自动代理生成器标签
自动代理生成器:用来完成代理对象的自动创建功能的 - 创建测试类
前置通知 @Beforet:在业务逻辑的前面的增加的功能案例
接口类:
public interface Someservice {
void doSome(String name,int age);
}
接口实现类:
public class SomeserviceImpl implements Someservice {
@Override
public void doSome(String name,int age) {
//在doSome方法增加一个功能,在doSome执行之前,输出方法执行的时间
System.out.println("------目标方法执行doSome()-------");
}
}
切面类:
@Aspect
public class MyaspectJ {
@Before(value = "execution(void cn.com.Ycy.spring_aspectJ.bao01.SomeserviceImpl.doSome(String,int))")
public void myBefore(JoinPoint joinPoint){
System.out.println("方法的定义"+joinPoint.getSignature());
System.out.println("方法的名称"+joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println(arg);
}
System.out.println("切面的功能:在目标方法执行之前需要输出时间:"+new Date());
}
}
切面类的分析
@Aspect:是aspectJ框架中的注解
表示当前类是切面类
切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
位置:在类定义的上面
在类中需要做什么
定义方法,方法是实现切面的功能的
方法的定义要求
- 公共方法 public
- 方法没有返回值 void
- 方法名自定义
- 方法可以有参数,也可以没有参数
如果有参数,不是自定义的,有几个可以选择使用
@Before:前置通知
属性:value,是切入点表达式,表示切面的功能执行的位置,目标类方法的位置
位置:在方法的上面
特点:
1 . 在目标的方法之前执行的
2. 不会改变目标方法的执行结果
3. 不会影响目标方法的执行
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"
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">
<!-- 声明目标对象 -->
<bean id="service" class="cn.com.Ycy.spring_aspectJ.bao01.SomeserviceImpl"/>
<!-- 声明切面对象 -->
<bean id="myAspect" class="cn.com.Ycy.spring_aspectJ.bao01.MyaspectJ"/>
<aop:aspectj-autoproxy/>
</beans>
分析:
aop:aspectj-autoproxy :
声明自动代理生产器:使用aspectJ框架内部的功能,来创建目标对象的代理对象。
创建代理对象是在内存中实现的
aspectj-autoproxy:会把spring容器中所有的目标对象,一次性都生成代理对象
测试类
@Test
public void test01(){
String config="ApplicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//从容器获取目标对象
Someservice service = (Someservice) ac.getBean("service");
//通过代理对象执行方法,实现目标方法执行时,增强了功能
service.doSome("张三",20);
}
点击查看:后置通知:@AfterReturning
点击查看:环绕通知:@Around
小细节讲解:
在aspect的切面类中的方法的权限可以去除的,参数也是可以的
@Aspect
public class MyaspectJ {
@Before(value = "execution(void cn.com.Ycy.spring_aspectJ.bao01.SomeserviceImpl.doSome(..))")
public void myBefore(){
System.out.println("切面的功能:在目标方法执行之前需要输出时间:"+new Date());
}
}
方法可以有参数,也可以没有参数
如果有参数,不是自定义的,有几个可以选择使用,指定通知方法中的参数:JoinPoint
如果你的切面功能需要用到方法的信息,就需要加入Joinpoint
这个JoinPoint参数的值是由框架赋予的,必须是第一个位置的参数
JoinPoint:业务方法,需要加入切面的业务方法
作用是:可以在通知方法中获取方法执行时的信息
- 方法名称
- 方法实参
joinPoint.getSignature() 获取业务方法的签命
joinPoint.getSignature().getName() 获取业务方法的名称
Object[] args = joinPoint.getArgs() 获取业务方法的参数变量
代码演示
@Aspect
public class MyaspectJ {
@Before(value = "execution(void cn.com.Ycy.spring_aspectJ.bao01.SomeserviceImpl.doSome(String,int))")
public void myBefore(JoinPoint joinPoint){
System.out.println("方法的定义"+joinPoint.getSignature());
System.out.println("方法的名称"+joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println(arg);
}
System.out.println("切面的功能:在目标方法执行之前需要输出时间:"+new Date());
}
}
输出结果:
方法的定义void cn.com.Ycy.spring_aspectJ.bao01.Someservice.doSome(String,int)
方法的名称doSome
张三
20
切面的功能:在目标方法执行之前需要输出时间:Sun Aug 02 21:43:33 CST 2020
-----目标方法执行doSome()-------