Spring Aop

AOP

底层用的仍然是jdk的动态代理

切面表达式

符号 意义
* 0至多个任意字符
.. 用在方法参数中,表示任意多个参数;用在包名后,表示当前包及其子包路径
+ 用在类名后,表示当前类及其子类;用在接口后,表示当前接口及其实现类

举例:

  • 规则:execytion(访问权限 方法返回值 方法声明(参数) 异常类型)

  • execution(public * *(..))
    
    • 指定切入点为:任意公共方法
  • execution(* set*(..))
    
    • 指定切入点为:任何一个以“set”开始的方法。
  • execution(* com.xyz.service.*.*(..))
    
    • 指定切入点为:定义在service包里的任意类的任意方法。
  • execution(* com.xyz.service..*.*)
    
    • 指定切入点为:定义在service包或者子包里面的任意类的任意方法。“。。”出现在包名时,后面必须跟“*”,表示包、子包下的所有类。
  • execution(* *..service.*.*(..))
    
    • 指定所有包下的service子包下所有类(接口)中所有方法为切入点
  • execution(* *.service.*.*(..))
    
    • 指定只有一级包下的service子包下所有类(接口)中所有方法为切入点

代理例子:

  • 目标接口

    public interface SomeService{
        void doSome(String name,Integer age);
        String doOther(String name,Integer age);
        String doFirst(String name,Integer age);
        void doSecond();
        void doTird();
    }
    
  • 目标对象

    public SomeServiceImpl implements SomeService{
        public void doSome(String name,Integer age){
            System.out.println("doSome==="+"name=  "+name+"; age=  "+age)
        }
        public String doOther(String name,Integer age){
            System.out.println("doOther==="+"name=  "+name+"; age=  "+age)
            return "abc";
        }
        
        public String doFirst(String name,Integer age){
            System.out.println("doFirst==="+"name=  "+name+"; age=  "+age)
            return "doFirst";
        }
        public void doSecond(){
            System.out.println("doSecond"+10/0)
        }
        public void doTird(){
            System.out.println("doThird");
        }
    }
    
  • 切面类

    @Aspect
    public class MyAspect{
        //公共方法 方法参数必须是固定的   执行时间before  执行位置 execution
        //JoinPoint必须再第一个参数
        @Before(value = "execution(public void com.*.ba01.SomeServiceImpl.dosome(String,Integer))")
    	public  void myBefore(JoinPoint jp){
            System.out.println("方法的签名"+jp.getSignature());
            System.out.println("方法的名称"+jp.getSignature().getName());
            System.out.println("前置:切面功能,再目标方法执行之前输出执行时间"+ new Date());
        }
        //公共方法,没有返回值,方法有参数
        @AfterReturning(value:"execution=(* *..SomeserviceImpl.doSome(..))",returning)
        public void myAfterReturing(JoinPoint jp,Object res){
            System.out.println("后置通知,再目标方法执行之后执行"+res)
        }
        /**
        环绕通知 功能最强的通知,在目标方法的前和后都增强功能。控制目标方法是否被调用执行 修改原来的目标方法的执行结果。影响最后的调用结果 等同于jdk InvocationHandler接口
        **/
        @Around(vlaue="execution(* *..SomeServiceImpl.doFirst(..))")
        public Object myAround(ProceedingJoinPoint pjp){
            String name = "";
            Object result = null;
            result = pjp.proceed();  
            //获取参数
            Object args[] = pjp.getArgs();
            if(args!=null&&args.length()>1){
                Object arg = args[0];
                name = (Stirng) arg;
            }
            System.out.println("环绕通知,目标方法执行之前的时间"+ new Date());
            //目标方法的调用
            pjp.proceed();    // method.invoke();
            System.out.println("环绕通知,目标方法执行之后");
            //改变目标输出结果
            if(result!=null){
                result = "修改后的内容";
            }
            return result;
        }
        @AfterThrowing(value="execution(* *..SomeServiceImpl.doSecond(..)")
        public void afterThrowing(Exception ex){
            System.out.println("异常通知:方法执行发生异常:"+ex.getMessage());
        }
        @After(value="execution=(* *..SomeServiceImpl.dothird(..))")
        public void after(){
            System.out.println("最终通知");
        }
        
        
        @Pointcut(value="execution=(* *..SomeserviceImpl.doThired(..))")
        public void mypt(){
        }
        @After(value="mypt()")
        public void testPoincut(){
            
        }
    }
    
  • xml applicationContext.xml

    <bean id="someService" class="someServiceImpl"></bean>
    <bean id="myAspect" class="MyAspect"></bean>
    <!--声明自动代理生成器-->
    <aop:aspectj-qutoproxy />
    
    <!--如果要使用CJLIB需要使用下面这个-->
    <aop:aspectj-qutoproxy proxy-target-class="true"/>
    

有接口使用jdk的InvocationHandler 没有接口使用CGLIB方式

posted @   Tian-Jotian-Yongxing  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示