基于配置文件
1.首先在pom.xml中导入SpringAOP包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
2.在applicationContext.xml中完成配置
spring和切面整合在一起,就不需要把类放到代理工厂中,spring内置了代理工厂
创建bean的时候会检查,当前bean是否被切点表达式选中,若有,则取出来时就为代理类
<!--配置AOP-->
<!--引入aop命名空间-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy><!--引入头文件-->
<bean id="myAspect" class="net.milkytea.aop.MyAspect"></bean>
<aop:config>
<aop:aspect ref="myAspect"><!--myAspect切面类-->
<!--设置切点,用表达式选择当前的切点
该表达式是对方法签名的筛选
方法签名包括:访问限定修饰符public、返回值、名字、参数
public可以不写,*是通配符表示可以返回任意类型的值
以net.milkytea开头,以service.impl结尾的全部类,全部方法,中间省略任意层级
()表示对参数进行筛选 括号里的..表示任意参数,有没有参数,或有多少都可以-->
<aop:pointcut id="logPc" expression="execution(* net.milkytea..*.service.impl.*.*(..))"/>
<!--设置增强哪些切点,该类被后置通知拦截了-->
<aop:after-returning method="afterReturning" returning="result" pointcut-ref="logPc"/>
<aop:after-throwing method="afterThrowing" throwing="e" pointcut-ref="logPc"/>
</aop:aspect>
</aop:config>
3.在aop文件下创建MyAspect类
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/*
*advice:通知
* aspect:切面
* pointcut:切点 所有连接点的集合
* Joinpoint:连接点 待处理方法
*/
public class MyAspect {
//5个时间节点称之为通知 advice
//前置通知,spring把参数都封装成Joinpoint,也就是连接点,防止调用目标方法,执行方法
public Boolean before(JoinPoint joinPoint) {
return true;
}
//环绕通知
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result=proceedingJoinPoint.proceed();//执行目标方法,相当于method.invoke(),已经把方法的参数封装好了
return result;
}
//后置通知
public void afterReturning(JoinPoint joinPoint,Object result){
System.out.println(new Date() + "use args" +
Arrays.toString(joinPoint.getArgs()) + "use " + joinPoint.getSignature() + " get " + result + " as result");
}
//异常通知
public void afterThrowing(JoinPoint joinPoint,Exception e){
}
//最终通知
public void after(JoinPoint joinPoint){
}
}
4.在mapper文件下创建UserMapper类
import org.springframework.stereotype.Repository;
@Repository
public class UserMapper{
public void sayHello(){
System.out.println("hello");
}
}
5.在service.impl文件下创建接口UserService
public interface UserService {
void save();
public void doService();
}
6.并创建实现类UserServiceImpl
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("save");
}
@Autowired//自动注入
UserMapper userMapper;
@Override
public void doService() {
userMapper.sayHello();
}
}
7.在main方法中写入
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)applicationContext.getBean("userServiceImpl");
userService.doService();
结果输出:
hello
Sun Jan 16 22:24:51 CST 2022use args[]use void net.milkytea.ioc.service.UserService.doService() get null as result
延伸:
基于JDK的切面要求目标类有父类
基于cglib的切面实现不要求目标类有父类
基于注解
1.先在applicationContext.xml中配置
<!--开启注解扫描-->
<context:component-scan base-package="net.milkytea"/>
<!--基于注解的切面实现-->
<aop:aspectj-autoproxy/>
2.在基于配置文件的基础上修改myAspect类
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component//组件,将MyAspect放入组件
@Aspect//将当前类设置为切面
public class MyAspect {
//在切面里配置切点
//用一个方法封装切点
@Pointcut("execution(* net.milkytea..*.service.impl.*.*(..))")
public void logPc(){}
@Before("logPc()")//指定通知的切点名字
public Boolean before(JoinPoint joinPoint) {
return true;
}
//环绕通知
@Around("logPc()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result=proceedingJoinPoint.proceed();//执行目标方法,相当于method.invoke(),已经把方法的参数封装好了
return result;
}
//后置通知
@AfterReturning(pointcut = "logPc()",returning = "result")
public void afterReturning(JoinPoint joinPoint,Object result){
System.out.println(new Date() + "use args" +
Arrays.toString(joinPoint.getArgs()) + "use " + joinPoint.getSignature() + " get " + result + " as result");
}
//异常通知
@AfterThrowing(pointcut = "logPc()",throwing = "e")
public void afterThrowing(JoinPoint joinPoint,Exception e){
}
//最终通知
@After("logPc()")
public void after(JoinPoint joinPoint){
}
}