详细总结什么是SpringAOP——面试一点通

【华为OD技术面试-面试官问的题 】线程池的工作流程,线程池的拒绝策略,SpringAOP?原理?等问题 其中,插件方式和物理分页方式可以自定义分页逻辑,提供更多的分页功能和灵活性。Spring AOP 基于代理模式实现,可以对 Java 对象进行代理并拦截方法调用,实现横向代码的复用,使得应用系统的代码更加清晰,易于维护和扩展。🔧 自动配置:Spring Boot 根据应用程序的依赖关系和配置文件,自动配置 Spring 环境,使得应用程序的搭建和部署更加方便和快速。🚀 简化配置:Spring Boot 通过自动配置、Starter 等方式,极大地简化了应用的配置工作,开箱即用,减少了开发人员的工作量。 阅读详情

前言:

首先看百度的专业术语:
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP使用场景:

AOP用来封装横切关注点,具体可以在下面的场景中使用:

Authentication 权限

Caching 缓存

Context passing 内容传递

Error handling 错误处理

Lazy loading 懒加载

Debugging  调试

logging, tracing, profiling and monitoring 记录跟踪 优化 校准

Performance optimization 性能优化

Persistence  持久化

Resource pooling 资源池

Synchronization 同步

Transactions 事务

一、为什么用aop:

1就是为了方便,看一个国外很有名的大师说,编程的人都是“懒人”,因为他把自己做的事情都让程序做了。用了aop能让你少写很多代码,这点就够充分了吧

2就是为了更清晰的逻辑,可以让你的业务逻辑去关注自己本身的业务,而不去想一些其他的事情,这些其他的事情包括:安全,事物,日志等。

二、AOP中的相关概念

专业的概念定义:

Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点): 表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点): 表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强): Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象): 织入 Advice 的目标对象.。
Weaving(织入): 将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程

通俗的解释:

1.通知(Advice)

就是你想要的功能,也就是上面说的 安全,事物,日志等。你给先定义好把,然后在想用的地方用一下。

2.连接点(JoinPoint)

这个更好解释了,就是spring允许你使用通知的地方,那可真就多了,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点.其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。

3.切入点(Pointcut)

上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。

4.切面(Aspect)

切面是通知和切入点的结合。现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。

5.引入(introduction)

允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗

6.目标(target)

引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。

7.代理(proxy)

怎么实现整套aop机制的,都是通过代理,这个一会给细说。

8.织入(weaving)

把切面应用到目标对象来创建新的代理对象的过程。有3种方式,spring采用的是运行时,为什么是运行时,后面解释。

关键就是: 切点定义了哪些连接点会得到通知

三、如何使用Spring AOP:

教你怎么切:

我来教你们怎么切,其实很形象,从xml开始切,首先,在切入方法之前执行什么,这就是before,然后,开始调用方法,在方法中做什么,这就是after,当方法执行完毕,最后开始返回一个值,就是afterreturnning,after throwing

可以通过配置文件或者编程的方式来使用Spring AOP。

配置可以通过xml文件来进行,大概有四种方式:

  1.    配置ProxyFactoryBean,显式地设置advisors, advice, target等
    
  2.    配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从容器中获得的其实已经是代理对象
    
  3.    通过<aop:config>来配置
    
  4.    通过<aop: aspectj-autoproxy>来配置,使用AspectJ的注解来标识通知及切入点
    

也可以直接使用ProxyFactory来以编程的方式使用Spring AOP,通过ProxyFactory提供的方法可以设置target对象, advisor等相关配置,最终通过 getProxy()方法来获取代理对象

四、多种方式使用AOP

我们来实际的用代码感受一下
1.在 Package【pojo】下新建一个【Landlord】类:
在这里插入图片描述
2.在 Package【aspect】下新建一个中介商【Broker】类:
在这里插入图片描述3.在 applicationContext.xml 中配置自动注入,并告诉 Spring IoC 容器去哪里扫描这两个 Bean:
在这里插入图片描述
4.在 Package【test】下编写测试代码:
在这里插入图片描述
5.执行看到效果:
在这里插入图片描述

五、使用注解来开发 Spring AOP:

使用注解的方式已经逐渐成为了主流,所以我们利用上面的例子来说明如何用注解来开发 Spring AOP
第一步:选择连接点
Spring 是方法级别的 AOP 框架,我们主要也是以某个类额某个方法作为连接点,另一种说法就是:选择哪一个类的哪一方法用以增强功能。
我们在这里就选择上述 Landlord 类中的 service() 方法作为连接点。
第二步:创建切面
选择好了连接点就可以创建切面了,我们可以把切面理解为一个拦截器,当程序运行到连接点的时候,被拦截下来,在开头加入了初始化的方法,在结尾也加入了销毁的方法而已,在 Spring 中只要使用
注意: 被定义为切面的类仍然是一个 Bean ,需要 @Component 注解标注
代码部分中在方法上面的注解看名字也能猜出个大概,下面来列举一下 Spring 中的
AspectJ 注解:
注解 说明
@Before 前置通知,在连接点方法前调用
@Around 环绕通知,它将覆盖原有方法,但是允许你通过反射调用原有方法
@After 后置通知,在连接点方法后调用
@AfterReturning 返回通知,在连接点方法执行并正常返回后调用,要求连接点方法在执行过程中没有发生异常
@AfterThrowing 异常通知,当连接点方法异常时调用
有了上表,我们就知道 before() 方法是连接点方法调用前调用的方法,而 after() 方法则相反,这些注解中间使用了定义切点的正则式,也就是告诉 Spring AOP 需要拦截什么对象的什么方法,下面讲到。
第三步:定义切点
在上面的注解中定义了 execution 的正则表达式,Spring 通过这个正则表达式判断具体要拦截的是哪一个类的哪一个方法:
@Pointcut(“execution(* com.wtr.apodemo1….(…))”)
@Pointcut(“execution(* com.wtr.apodemo1.pojo..(…))”)
@Pointcut(“execution(* com.wtr.apodemo1.pojo.Landlord.(…))")
@Pointcut("execution(
com.wtr.apodemo1.pojo.Landlord.service(…))”)

依次对这个表达式作出分析:

execution:代表执行方法的时候会触发
*:代表任意返回类型的方法
pojo.Landlord:代表类的全限定名
service():被拦截的方法名称
通过上面的表达式,Spring 就会知道应该拦截 pojo.Lnadlord 类下的 service() 方法。上面的演示类还好,如果多出都需要写这样的表达式难免会有些复杂,我们可以通过使用 @Pointcut 注解来定义一个切点

第四步:测试 AOP
结果还是一样的
环绕通知
我们来探讨一下环绕通知,这是 Spring AOP 中最强大的通知,因为它集成了前置通知和后置通知,它保留了连接点原有的方法的功能,所以它及强大又灵活

使用 XML 配置开发 Spring AOP

注解是很强大的东西,但基于 XML 的开发我们仍然需要了解,我们先来了解一下 AOP 中可以配置的元素:
AOP 配置元素 用途 备注
aop:advisor 定义 AOP 的通知其 一种很古老的方式,很少使用
aop:aspect 定义一个切面 ——
aop:before 定义前置通知 ——
aop:after 定义后置通知 ——
aop:around 定义环绕通知 ——
aop:after-returning 定义返回通知 ——
aop:after-throwing 定义异常通知 ——
aop:config 顶层的 AOP 配置元素 AOP 的配置是以它为开始的
aop:declare-parents 给通知引入新的额外接口,增强功能 ——
aop:pointcut 定义切点 ——
有了之前通过注解来编写的经验,并且有了上面的表,我们将上面的例子改写成 XML 配置很容易(去掉所有的注解):
在这里插入图片描述
运行测试程序,依然能看到正确结果。

六、整合事物管理:

在这里插入图片描述
在这里插入图片描述
如下图:给需要开启事务的方法上添加事务注解
在这里插入图片描述

七、Spring AOP代理对象的生成

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。下面我们来研究一下Spring如何使用JDK来生成代理对象,具体的生成代码放在JdkDynamicAopProxy这个类中,直接上相关代码:

/**
    * <ol>
    * <li>获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false)
    * <li>检查上面得到的接口中有没有定义 equals或者hashcode的接口
    * <li>调用Proxy.newProxyInstance创建代理对象
    * </ol>
    */
   public Object getProxy(ClassLoader classLoader) {
       if (logger.isDebugEnabled()) {
           logger.debug("Creating JDK dynamic proxy: target source is " +this.advised.getTargetSource());
       }
       Class[] proxiedInterfaces =AopProxyUtils.completeProxiedInterfaces(this.advised);
       findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
       return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

下面的问题是,代理对象生成了,那切面是如何织入的?

我们知道InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。而通过JdkDynamicAopProxy的签名我们可以看到这个类其实也实现了InvocationHandler,下面我们就通过分析这个类中实现的invoke()方法来具体看下Spring AOP是如何织入切面的。

publicObject invoke(Object proxy, Method method, Object[] args) throwsThrowable {
       MethodInvocation invocation = null;
       Object oldProxy = null;
       boolean setProxyContext = false;
   TargetSource targetSource = this.advised.targetSource;
   Class targetClass = null;
   Object target = null;

   try {
       //eqauls()方法,具目标对象未实现此方法
       if (!this.equalsDefined && AopUtils.isEqualsMethod(method)){
            return (equals(args[0])? Boolean.TRUE : Boolean.FALSE);
       }

       //hashCode()方法,具目标对象未实现此方法
       if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)){
            return newInteger(hashCode());
       }

       //Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
       if (!this.advised.opaque &&method.getDeclaringClass().isInterface()
                &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations onProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised,method, args);
       }

       Object retVal = null;

       if (this.advised.exposeProxy) {
            // Make invocation available ifnecessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
       }

       //获得目标对象的类
       target = targetSource.getTarget();
       if (target != null) {
            targetClass = target.getClass();
       }

       //获取可以应用到此方法上的Interceptor列表
       List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);

       //如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)
       if (chain.isEmpty()) {
            retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);
       } else {
            //创建MethodInvocation
            invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            retVal = invocation.proceed();
       }

       // Massage return value if necessary.
       if (retVal != null && retVal == target &&method.getReturnType().isInstance(proxy)
                &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned"this" and the return type of the method
            // is type-compatible. Notethat we can't help if the target sets
            // a reference to itself inanother returned object.
            retVal = proxy;
       }
       return retVal;
   } finally {
       if (target != null && !targetSource.isStatic()) {
            // Must have come fromTargetSource.
           targetSource.releaseTarget(target);
       }
       if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
       }
   }
}

主流程可以简述为: 获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint; 如果没有,则直接反射执行joinpoint。而这里的关键是通知链是如何获取的以及它又是如何执行的,下面逐一分析下。

首先,从上面的代码可以看到,通知链是通过Advised.getInterceptorsAndDynamicInterceptionAdvice()这个方法来获取的,我们来看下这个方法的实现:

public List<Object>getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {
               MethodCacheKeycacheKey = new MethodCacheKey(method);
               List<Object>cached = this.methodCache.get(cacheKey);
               if(cached == null) {
                        cached= this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                                           this,method, targetClass);
                        this.methodCache.put(cacheKey,cached);
               }
               returncached;
     }

可以看到实际的获取工作其实是由AdvisorChainFactory. getInterceptorsAndDynamicInterceptionAdvice()这个方法来完成的,获取到的结果会被缓存。

下面来分析下这个方法的实现:

/**
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
*/
publicList getInterceptorsAndDynamicInterceptionAdvice(Advised config, Methodmethod, Class targetClass) {
// This is somewhat tricky… we have to process introductions first,
// but we need to preserve order in the ultimate list.
List interceptorList = new ArrayList(config.getAdvisors().length);

   //查看是否包含IntroductionAdvisor
   boolean hasIntroductions = hasMatchingIntroductions(config,targetClass);

   //这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptor
   AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

   Advisor[] advisors = config.getAdvisors();
    for (int i = 0; i <advisors.length; i++) {
       Advisor advisor = advisors[i];
       if (advisor instanceof PointcutAdvisor) {
            // Add it conditionally.
            PointcutAdvisor pointcutAdvisor= (PointcutAdvisor) advisor;
            if(config.isPreFiltered() ||pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
                //TODO: 这个地方这两个方法的位置可以互换下
                //将Advisor转化成Interceptor
                MethodInterceptor[]interceptors = registry.getInterceptors(advisor);

                //检查当前advisor的pointcut是否可以匹配当前方法
                MethodMatcher mm =pointcutAdvisor.getPointcut().getMethodMatcher();

                if (MethodMatchers.matches(mm,method, targetClass, hasIntroductions)) {
                    if(mm.isRuntime()) {
                        // Creating a newobject instance in the getInterceptors() method
                        // isn't a problemas we normally cache created chains.
                        for (intj = 0; j < interceptors.length; j++) {
                           interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j],mm));
                        }
                    } else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
       } else if (advisor instanceof IntroductionAdvisor){
            IntroductionAdvisor ia =(IntroductionAdvisor) advisor;
            if(config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
                Interceptor[] interceptors= registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
       } else {
            Interceptor[] interceptors =registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
       }
   }
   return interceptorList;

}

这个方法执行完成后,Advised中配置能够应用到连接点或者目标类的Advisor全部被转化成了MethodInterceptor.

接下来我们再看下得到的拦截器链是怎么起作用的。

           if (chain.isEmpty()) {
            retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);
        } else {
            //创建MethodInvocation
            invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            retVal = invocation.proceed();
        }

从这段代码可以看出,如果得到的拦截器链为空,则直接反射调用目标方法,否则创建MethodInvocation,调用其proceed方法,触发拦截器链的执行,来看下具体代码

 public Object proceed() throws Throwable {
   //  We start with an index of -1and increment early.
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()- 1) {
       //如果Interceptor执行完了,则执行joinPoint
       return invokeJoinpoint();
   }

   Object interceptorOrInterceptionAdvice =
       this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
   
   //如果要动态匹配joinPoint
   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher){
       // Evaluate dynamic method matcher here: static part will already have
       // been evaluated and found to match.
       InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
       //动态匹配:运行时参数是否满足匹配条件
       if (dm.methodMatcher.matches(this.method, this.targetClass,this.arguments)) {
            //执行当前Intercetpor
            returndm.interceptor.invoke(this);
       }
       else {
            //动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
            return proceed();
       }
   }
   else {
       // It's an interceptor, so we just invoke it: The pointcutwill have
       // been evaluated statically before this object was constructed.
       //执行当前Intercetpor
       return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }

}

其他的一些内容:

AOP中的Joinpoint可以有多种类型:构造方法调用,字段的设置和获取,方法的调用,方法的执行,异常的处理执行,类的初始化。也就是说在AOP的概念中我们可以在上面的这些Joinpoint上织入我们自定义的Advice,但是在Spring中却没有实现上面所有的joinpoint,确切的说,Spring只支持方法执行类型的Joinpoint。

Advice 的类型:

before advice, 在 join point 前被执行的 advice. 虽然 before advice 是在 join point 前被执行, 但是它并不能够阻止 join point 的执行, 除非发生了异常(即我们在 before advice 代码中, 不能人为地决定是否继续执行 join point 中的代码)

after return advice, 在一个 join point 正常返回后执行的 advice
after throwing advice, 当一个 join point 抛出异常后执行的 advice
after(final) advice, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice.around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是**最常用的 advice.introduction,**introduction可以为原有的对象增加新的属性和方法。

*以上是一个SpringAOP的大致总结,后面还会继补充,请大家持续关注~

最后:

愿大家前程似锦,加油!!

SpringAop源码分析---Spring面试系列--源码解析 SpringAop源码分析 AOP简介 概念 切面(Aspect) :官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”。连接点(Joinpoint) :程序执行过程中的某一行为。通知(Advice) :“切面”对于某个“连接点”所产生的动作。切入点(Pointcut) :匹配连接点的断言,在AOP中通知和一个切入点表达式关联。目标对象(Target Object) :被一个或者多个切面所通知的对象。AOP代理(AOP Proxy) 在Spring AOP中有两种代理方式,JDK动态 阅读详情

相关推荐

【Autosar】学习总结-MCAL

一、简介 MCAL:微控制器抽象层;位于BSW层中的最下层; MCAL细分,可将驱动分为:微控制器驱动、存储器驱动、通信驱动、IO驱动: 二、MCAL的配置(EB-Tresos) 1.PORT 我理解的PORT:MCAL层中的IO驱动组中的pin脚总体配置: Port就是芯片上的每个pin脚,可以配置成DIO ADC PWM ICU等单引脚的功能,也能配置成CAN的TX或者RX、SPI的MOSI等等其他功能的单个pin脚功能; 总之,PORT就是芯片上的具体的某个引脚。 配置

zDavid_2018的博客 3万+

SpringAOP超详细图文解释(深入学习笔记可用于面试)

记录什么高频面径之SpringAOP底层原理以及对应的开发使用详细讲解;AOP 面向方面编程(Aspect-oriented Programming,151)通过提供关于程序结构的另一种思考方式,补充了面向对象编程。在 OOP 中,模块化的关键单元是类,而在 AOP 中,模块化的单元是方面。方面支持跨多个类型和对象的关注(例如事务管理)的模块化。

sakura的博客 2520

MEG预处理-Brainstorm

Brainstorm下载和安装 去Brainstorm官网进行下载:打开网页后,点击左侧Download;在跳出来的界面中进行简单的注册,注册完成后可以进行下载 解压后得到“brainstorm3”的文件夹,里面包含Brainstorm工具包的所有文件,把这个文件夹放在某个路径如"E:\matlab_tools\brainstorm3"即可 同样在某个路径建立空的文件夹命名为:brainstorm_db用于工具包运行过程中自动存储生成的文件,所以这个文件中生成的数据不要手动移动删除 在Matlab中,把.

AxeChen的博客 6124

谈谈你对Spring AOP理解【面试】

面试中经常会被问到Spring AOP的原理,相信大家都是条件反射的想到JDK代理和CGLib代理,本文将介绍这两个代理的区别及实现一个Spring AOP实例

夏夜凉月 1493

Ansys Zemax导入CAD文件避坑指南:STL/STEP/IGES格式选择与性能优化

本文深度解析了在Ansys Zemax中导入CAD文件的核心要点与性能优化策略。针对STL、STEP、IGES等主流格式,详细对比了其几何表示、精度与适用场景差异,并提供了基于模型特征的格式选择决策树。文章重点分享了体元、弦公差等高级参数的调优技巧,以及处理复杂装配体和避免精度陷阱的实战指南,旨在帮助光学工程师提升仿真效率与结果可靠性。

weixin_29202687的博客 436

FISCO BCOS 三、多群组部署以及新节点加入群组

本章主要以星形组网和并行多组组网拓扑为例,指导您了解如下内容:了解如何使用创建多群组区块链安装包;了解创建的多群组区块链安装包目录组织形式;学习如何启动该区块链节点,并通过日志查看各群组共识状态;学习如何向各群组发送交易,并通过日志查看群组出块状态;了解群组内节点管理,包括节点入网、退网等;了解如何新建群组。

qq_63235624的博客 2920

聊聊Spring中的AOP(笔面试必备)

| 作者:江夏| 知乎:https://www.zhihu.com/people/1024-paper-96| GitHub:https://github.com/JiangXia-1024?tab=repositories| 博客地址:https://blog.youkuaiyun.com/qq_41153943              本文大概10288字读完共需10分钟我们在使用Spring框架的过程中,其实就是为了使用IOC和AO

江夏、的博客 569

有之以为利,无之以为用,在 RAP 开发里的虚实取舍

摘要(149字) SAP RAP框架通过"有"与"无"的哲学平衡实现业务应用价值。其"有"体现在CDS视图、行为定义、服务绑定等具体对象,为系统提供形体;而"无"则表现为保留的扩展空间、未暴露的实现细节和框架托管的生命周期。在采购审批应用中,RAP既通过明确定义的行为模型建立业务语义,又通过验证、动作等机制保持灵活性。这种架构既确保核心功能稳固,又为未来演进留出余地,印证了"有之以为利,无之以为用"的技术智慧

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1304

面试被问到Spring AOP,你解释清楚了吗?

AOP(Aspect Oriented Programming):面向切面编程,它是一种思想,是对某一件事情的集中处理。看不懂没关系,继续往下看~举例说明例如我们要实现一个用户登录权限的校验,如果不使用AOP,我们就需要在所有的页面中都要各自实现或者调用用户登录验证的方法(出登录和注册页面不需要),而使用AOP后,我们只需要在某一处配置一下,就可以实现所有需要判断用户登录验证的地方进行用户登录验证了,不再需要每个方法中都写相同的用户登录验证了~@Aspect //告诉序程序,这个一个切面类。

LYJbao的博客 895

机器学习kaggle报告-Facial Keypoints Detection【完整解题过程+代码】

在处理面部关键点检测任务时,首先需要将存储在 CSV 文件中的图像数据转换为可以显示和分析的图像。数据集中每个图像是以一个一维数组的形式存储,其中包含了图像的所有像素值。为了将这些数据转化为实际的图像,我们需要按照一定的规则将这些像素值重新排列为一个二维矩阵(即图像的行列)。下面是一个案例,展示了如何将数据集中的图像数据转化为图片。转化过程读取CSV文件:首先,我们需要读取包含图像数据的 CSV 文件,通常该文件包含多张图像的像素值。每一行表示一张图像,并且包含图像的像素值列表。提取图像数据。

一键难忘的博客 3353

【思考模型框架】采用双钻模型:发散(桌面研究/用户访谈)→收敛(需求归类/优先级排序),输出需求规格书、追踪矩阵及产品待办清单。

设计思维双钻模型是一种以用户为中心的需求管理方法,通过"发散-收敛"的双循环确保问题定位准确、方案切实可行。第一钻石(探索→定义)聚焦"找对问题",运用用户访谈、田野调查等方法挖掘真实需求;第二钻石(开发→交付)解决"做对方案",通过原型测试、A/B测试验证可行性。该模型强调低保真验证、多团队协作和真实用户测试,避免资源浪费与伪需求开发。典型应用场景包括产品功能优化、用户体验提升等需要精准落地的需求场景。核心价值在于建立从用户痛点到解决方案的可控闭

奶爸的编程之路,也就一周冷个三天 319

Spring AOP 深入剖析

AOP是Spring提供的关键特性之一。AOP即面向切面编程,是OOP编程的有效补充。使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统。从而避免了在业务逻辑的代码中混入很多的系统相关的逻辑——比如权限管理,事物管理,日志记录等等。这些系统性的编程工作都可以独立编码实现,然后通过AOP技术切入进系统即可。从而达到了将不同的关注点分离出来的效果。本文深入剖...

weixin_34304013的博客 604

SAP_MM&FI模块-质保金标准解决方案详解

主要讲述了SAP系统质保金的标准实现方案,包含业务背景、后台配置、前台业务操作记录,以及关键点的AI解释;

风沙的博客 685

面试遇到SpringAOP不要慌

Aspect Oriented Programming(面向切面编程)是一种编程思想。所谓切面可以理解为特定的一些方法。所以AOP可以看成是面向特定的方法进行编程。比如上一篇文章提到的拦截器,就是AOP的体现。它针对特定的方法进行统一的管理,让代码模块化,易于维护。包括ExceptionAdvice、ResponseBodyAdvice(统一异常处理、统一数据返回格式)都运用了AOP的思想。定义一个注解:@Retention(RetentionPolicy.RUNTIME)//表示运行时,仍然存在。

HYY的博客 1212

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

SpringAOP是啥,怎么用?

SpringAOP是啥,怎么用? 一、面试问题:什么是SpringAOP? SpringAOP的全称是(Aspect Oriented Programming)中文翻译过来是面向切面编程,个人理解:主要意思是我们的传统架构至上而下,后期想要从中间切入写代码添加功能,比如日志、权限、事务等,这时候我们就需要写使用代理模式写,而springaop就是专门把这一块写代码的地方给抽象了出来称为切面,从而解决的代码混乱的问题,它的底层实现也是基于代理模式(动态代理)完成的。 二、SpringAOP的应用场景有

Object_de_Father的博客 19万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java面试题(四) - SpringAOP的原理

昨天进行的面试,被问到了SpringAOP的原理问题,我当时只知道是通过动态代理实现的,其余的一脸懵逼状态。 问:请说一下SpringAOP的原理。 答:SpringAOP是通过动态代理来实现的。 问:你说的动态代理是JDK的动态代理吗? 答:是的。 问:那被代理的类没有实现接口的情况,这是怎么实现的? 答:... 回来后,我搜索了很多资料、最后总结如下: (1) SpringAOP是动态代理来实...

梦缘的博客 6431

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

springAOP

AOP是Aspect Oriented Programming(面向切面编程),切面是指某一特定问题,所以AOP也可以理解为面向特定方法编程。比如我们在用户登录时设置登录校验拦截器,就是对“登录校验”这一类问题的统一处理,所以拦截器是AOP的一种应用,而AOP是一种思想,拦截器就是AOP思想的一种实现。而Spring框架也实现了这种思想,提供了拦截器技术的相关接口。同样的,统一数据返回格式和统一异常处理,也是AOP思想的一种实现。

2202_75439262的博客 954

备战2024秋招面试题-SpringAOP的原理

简单谈一下SpringAOP的原理以及算法题“前k个高频元素”

奔走的王木木Sir的博客 893

面试之springAOP IOC总结

SpringAOP和aspectJ AOP有什么区别?springbean的生命周期等. IOC IOC(Inversion Of Controll,控制反转)是一种设计思想,将原本在程序中手动创建对象的控制权,交由给Spring框架来管理。IOC容器是Spring用来实现IOC的载体,IOC容器实际上就是一个Map(key, value),Map中存放的是各种对象。 这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC容器就像是一个工厂,当需要创建一个对象,只需要配置好配置文件/注解

a_zhenxz的博客 305

九月最新-平安寿险Java面试,四次面试的详细流程。

昨天跟一个小伙伴聊天,说我天天都发的是BATBAT的,看得他都有点怀疑人生了,想让我扒一两篇保险公司的Java面试题,应该也是准备要去面试了。对于我这样的实力宠粉的人,怎么能不接受这样的要求,绝对不是我也不想扒BAT的面试题了,嗯。 这不,上网收集了好久的保险公司的面试题,然后再去掉重复的问题,剩下了这些我精选出来的。也希望对我的那位粉丝和各位都有所帮助。 一面 报文传输是否会进行加密,加密的方式是什么? 知道对称加密和非对称加密的区别和应用场景吗? 用MQ采集消息的时候,有没有做消息重复消费处理?怎么

程序员Monkey的专栏 8192

springAOP面试题

1.什么是SpringAop? 一般称为面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻 辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。 2.AOP的相关概念 (1)切面(Aspect): 在Spring Aop指定就是“切面类” ,切面类会管理着切点、通知。 (2)连接点(Join point): 在增强方法里使用,封装了核心方法信息,在增强方法里,通过joinPoint对象可以获

m0_54705036的博客 1万+

SpringAop(1)

一种规则Pointcut 的作⽤就是提供⼀组规则 (使⽤ AspectJ pointcut expression language 来描述), 告诉程序对哪些⽅法来进⾏功能增强。也就是@Around后边的字符串,描述了在哪里进行切入。对哪些的方法进行功能增强。(告诉哪些能被连接成切面,哪些不能被连接成切面,哪些能被Aop认识到,就是寻找匹配项)。这是切面的设置以及切面的逻辑@Slf4j@Component@Aspect//作用的范围是TestController。

syx050403的博客 1190

面试官:说说SpringAOP实现原理?

本文内容已收录至我的面试网站:www.javacn.siteAOP(Aspect-Oriented Programming,面向切面编程)是一种编程技术,它允许开发者在不改变现有代码的情况下,增加新的功能或行为,这些功能或行为被称为“切面”。AOP 可以通过预编译方式和运行期动态代理的方式来实现,它的主要目的是降低业务逻辑的耦合性,提高程序的可重用性和开发效率。AOP 常用于统一功能的处理,例如:...

磊哥聊Java 575

干了5年的Java面试官,把他喜欢问的几十个Spring面试题告诉我了

前言: Spring 框架知识是互联网公司面试必考知识点。对于开发同学来说,Spring 框架熟悉又陌生。 熟悉:开发过程中无时无刻不在使用 Spring 的知识点;陌生:对于基本理论知识疏于整理与记忆。导致很多同学面试时对于 Spring 相关的题目知其答案,但表达不够完整准确。 针对 Spring 面试题目,进行全面的梳理与解答,参考了公司面试题集,分享给大家。 主要内容: 基本概念面试题集(Spring 相关的概念梳理) 应用场景面试题集(各知识点不同使场景选型) 深度知识面试题集(底

豆汁 9415

SpringAOP

SpringAOP

Vampire的博客 915

SpringAop(2)

在新建java类中选择Annotation,并创建对象。@Target后边的是作用域的范围,说明了后边是作用在方法上的。@Retention是作用的生命周期,(RUNTIME)是运行时。但是这时候的注解并没有任何逻辑我们给他填上逻辑。@Component@Slf4j@Aspect//切点作用域在这里我们定义了一个切面类,通过@Around("@annotation(com.syx.aop.config.MyAspect)")来声明该切面类的作用范围。

syx050403的博客 911
上一篇: 分享一篇写的非常好的文章《如何掌握企业级技术和项目经验》,非常值得一看!
下一篇: 分享几道经典的sql笔试题——非常值得一看,受益匪浅系列,都是干货~~
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值