【Spring】Spring学习笔记---AOP之Aspect,基于JDK的切面的两种实现--配置文件和注解

基于配置文件

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){

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值