万字干货!Spring基于AOP事务控制实现原理全解

1.概述

对于一个系统应用而言,使用数据库进行数据存储是必然的,意味着开发过程中事务的使用及控制也是必不可少的,当然事务是数据库层面的知识点并不是Spring框架所提出的。使用JDBC开发时,我们使用connnection对事务进行控制,使用MyBatis时,我们使用SqlSession对事务进行控制,缺点显而易见,当我们切换数据库访问技术时,事务控制的方式总会变化,所以Spring 就在这些技术基础上,提供了统一的控制事务的接口。Spring的事务分为:编程式事务控制和声明式事务控制。

  • 编程式事务控制:Spring提供了事务控制的类和方法,使用编码的方式对业务代码进行事务控制,事务控制代码和业务操作代码耦合到了一起,开发中几乎不使用
  • 声明式事务控制: Spring将事务控制的代码封装,对外提供了Xml和注解配置方式,通过配置的方式完成事务的控制,可以达到事务控制与业务操作代码解耦合,开发中推荐使用

2.Spring事务管理和封装

2.1 原生事务控制

在没有框架对事务进行封装之前,我们都是使用底层的原生api来进行事务控制,如JDBC操作数据库控制事务

 

ini

复制代码

// 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 获取mysql数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","root", "root"); conn.setAutoCommit(false); // 获取statement statement = conn.createStatement(); // 执行sql,返回结果集 resultSet = statement.executeQuery("xxxx"); // 提交 conn.commit(); // 回滚 // conn.rollback();

这就是原生操作事务的流程,在我们使用Spring框架开发业务系统时也是离不了这样的事务操作的,如果每与数据库交互都需要按上面步骤进行操作,就会显得十分臃肿、重复编码,所以Spring对此进行了封装来提高编程的效率,让事务控制这一过程自动化、透明化,从而做到让开发者专注业务逻辑编码,无需关注事务控制,由Spring框架AOP切面完成即可。

2.2 Spring提供的事务API

Spring基于模版方法设计模式实现了事务控制的封装,核心API和模板类如下:

核心类解释
平台事务管理器PlatformTransactionManager是一个接口标准,实现类都具备事务提交、回滚和获得事务对象的功能,不同持久层框架可能会有不同实现方案
事务定义TransactionDefinition封装事务的隔离级别、传播行为、过期时间等属性信息
事务状态TransactionStatus存储当前事务的状态信息,如果事务是否提交、是否回滚、是否有回滚点等

事务管理器—PlatformTransactionManager

PlatformTransactionManager是事务管理器的顶层接口,只规定了事务的基本操作:创建事务,提交事物和回滚事务。

 

java

复制代码

public interface PlatformTransactionManager extends TransactionManager { ​ // 打开事务 TransactionStatus getTransaction(@Nullable TransactionDefinition definition)   throws TransactionException; ​ // 提交事务 void commit(TransactionStatus status) throws TransactionException; ​  // 回滚事务 void rollback(TransactionStatus status) throws TransactionException; }

Spring使用模板方法模式提供了一个抽象类AbstractPlatformTransactionManager,规定了事务管理器的基本框架,仅将依赖于具体平台的特性作为抽象方法留给子类实现,如mybatis框架的事务管理器是DatasourceTransactionManagerhibernate框架的事务管理器是HibernateTransactionManager,我曾经见过一个项目服务里的ORM框架同时使用了mybatis,hibernate两个框架,至于为啥?大概是想从hibernate转为mybatis吧....然后有这么一个问题,一个逻辑方法有两个数据库操作,一个是用mybatis实现的,一个是用hibernate实现,这个逻辑方法使用了@Transactional(rollbackFor = Exception.class),但是事务竟然没控制住~前面就是问题的原因所在,mybatishibernate的事务管理器都不是同一个,肯定控制不住事务的。

事务状态—TransactionStatus

存储当前事务的状态信息,如果事务是否提交、是否回滚、是否有回滚点等。

 

csharp

复制代码

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable { ​ /**  * 是否有Savepoint Savepoint是当事务回滚时需要恢复的状态  */ boolean hasSavepoint(); ​ /**  * flush()操作和底层数据源有关,并非强制所有数据源都要支持  */ @Override void flush(); ​ }

还从父接口TransactionExecution,SavepointManager中继承了其他方法

 

csharp

复制代码

/**  * 是否是新事务(或是其他事务的一部分)  */ boolean isNewTransaction(); ​ /**  * 设置rollback-only 表示之后需要回滚  */ void setRollbackOnly(); ​ /**  * 是否rollback-only  */ boolean isRollbackOnly(); ​ /**  * 判断该事务已经完成  */ boolean isCompleted(); /**  * 创建一个Savepoint  */ Object createSavepoint() throws TransactionException; ​ /**  * 回滚到指定Savepoint  */ void rollbackToSavepoint(Object savepoint) throws TransactionException; ​ /**  * 释放Savepoint 当事务完成后,事务管理器基本上自动释放该事务所有的savepoint  */ void releaseSavepoint(Object savepoint) throws TransactionException;

事务属性的定义—TransactionDefinition

TransactionDefinition封装事务的隔离级别、传播行为、过期时间等属性信息

 

csharp

复制代码

/**  * 返回事务的传播级别  */ default int getPropagationBehavior() {  return PROPAGATION_REQUIRED; } ​ /**  * 返回事务的隔离级别  */ default int getIsolationLevel() {  return ISOLATION_DEFAULT; } ​ /**  * 事务超时时间  */ default int getTimeout() {  return TIMEOUT_DEFAULT; } ​ /**  * 是否为只读事务(只读事务在处理上能有一些优化)  */ default boolean isReadOnly() {  return false; } ​ /**  * 返回事务的名称  */ @Nullable default String getName() {  return null; } ​ ​ /**  * 默认的事务配置  */ static TransactionDefinition withDefaults() {  return StaticTransactionDefinition.INSTANCE; }

2.3 Spring编程式事务实现

基于上面底层的API,开发者可以在代码中手动的管理事务的开启、提交、回滚等操作来完成编程式事务控制。在spring项目中可以使用TransactionTemplateTransactionCallback进行实现手动控制事务。

 

typescript

复制代码

  //设置事务的各种属性;可以猜测TransactionTemplate应该是实现了TransactionDefinition        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);        transactionTemplate.setTimeout(30000);                //执行事务 将业务逻辑封装在TransactionCallback中        transactionTemplate.execute(new TransactionCallback<Object>() {            @Override            public Object doInTransaction(TransactionStatus transactionStatus) {                    //....   业务代码           }       });

但是我们在开发过程中一般不使用编程式事务控制,因为比较繁琐不够优雅,一般是使用声明式进行事务控制,所以接下来就重点讲讲声明式事务。

项目推荐:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企业级系统架构底层框架封装,解决业务开发时常见的非功能性需求,防止重复造轮子,方便业务快速开发和企业技术栈框架统一管理。引入组件化的思想实现高内聚低耦合并且高度可配置化,做到可插拔。严格控制包依赖和统一版本管理,做到最少化依赖。注重代码规范和注释,非常适合个人学习和企业使用

Github地址github.com/plasticene/…

Gitee地址gitee.com/plasticene3…

微信公众号Shepherd进阶笔记

交流探讨qun:Shepherd_126

3.声明式事务

3.1 示例

@Transactional是Spring中声明式事务管理的注解配置方式,相信这个注解的作用大家都很清楚,直接来看看我们添加用户和角色的示例代码:

 

ini

复制代码

​  @Transactional(rollbackFor = Exception.class)  public void addUser(UserParam param) {      String username = param.getUsername();      checkUsernameUnique(username);      User user = PtcBeanUtils.copy(param, User.class);      userDAO.insert(user);      if (!CollectionUtils.isEmpty(param.getRoleIds())) {          userRoleService.addUserRole(user.getId(), param.getRoleIds());     } }

可以看出在Spring中进行事务管理非常简单,只需要在方法上加上注解@Transactional,Spring就可以自动帮我们进行事务的开启、提交、回滚操作。

3.2 实现原理

@EnableTransactionManagement说起,该注解开启注解声明式事务,所以我们就先来看看其定义:

 

less

复制代码

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement { ​ /**  * 用来表示默认使用JDK Dynamic Proxy还是CGLIB Proxy  */ boolean proxyTargetClass() default false; ​ /**  * 表示以Proxy-based方式实现AOP还是以Weaving-based方式实现AOP  */ AdviceMode mode() default AdviceMode.PROXY; ​ /**  * 顺序  */ int order() default Ordered.LOWEST_PRECEDENCE; ​ }

可以看出,和注解@EnableAspectJAutoProxy开启aop代理差不多,核心逻辑:@Import(TransactionManagementConfigurationSelector.class)TransactionManangementConfigurationSelector主要是往Spring容器中注入相关bean,核心逻辑如下:

 

scala

复制代码

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { ​ /** * Returns {@link ProxyTransactionManagementConfiguration} or * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY} * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, * respectively. */ @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {determineTransactionAspectClass()}; default: return null; } } }

3.2.1 如何生成代理类

AutoProxyRegistrar通过调用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);向容器中注册AbstractAdvisorAutoProxyCreator,这个类在之前总结的 Spring切面编程实现原理一文中重点解析过,是生成AOP代理类的核心实现所在。

UserService实现类中使用了@Transational来进行数据库事务控制,AuthService中不涉及到数据库事务处理,从图中可知UserService是被CGLIB动态代理生成的代理类,而AuthService是原生类,这就是AbstractAdvisorAutoProxyCreator实现的,

#getAdvicesAndAdvisorsForBean()会判断bean是否有advisor,有的话就通过动态代理生成代理对象注入到Spring容器中,这就是前面UserService代理对象的由来。

 

less

复制代码

protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { ​ List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }

#findEligibleAdvisors()顾名思义就是找到符合条件的advisor

 

ini

复制代码

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }

#findCandidateAdvisors()查找所有候选的advisor

 

kotlin

复制代码

@Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }

super.findCandidateAdvisors()就是获取spring内部规则的advisor,比如说事务控制的advisor:BeanFactoryTransactionAttributeSourceAdvisor

this.aspectJAdvisorsBuilder.buildAspectJAdvisors()是解析使用了@Aspect的切面类,根据切点表达式生成advisor。

#findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)调用AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);筛选出能匹配当前bean的advisor。

AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)会调用#canApply()方法:

 

java

复制代码

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } }

这里判断如果是PointcutAdvisor类型,就会调用canApply(pca.getPointcut(), targetClass, hasIntroductions);,上面提到的事务advisor:BeanFactoryTransactionAttributeSourceAdvisor正好符合。执行BeanFactoryTransactionAttributeSourceAdvisorTransactionAttributeSourcePointcut对象的matches()方法来进行是否匹配判断,然后根据当前bean的所有method遍历执行判断使用有@Transational注解,来到AbstractFallbackTransactionAttributeSourcecomputeTransactionAttribute()方法

 

kotlin

复制代码

@Nullable protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) { // Don't allow no-public methods as required. if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } ​ // The method may be on an interface, but we need attributes from the target class. // If the target class is null, the method will be unchanged. Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); ​ // First try is the method in the target class. TransactionAttribute txAttr = findTransactionAttribute(specificMethod); if (txAttr != null) { return txAttr; } ​ // Second try is the transaction attribute on the target class. txAttr = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } ​ if (specificMethod != method) { // Fallback is to look at the original method. txAttr = findTransactionAttribute(method); if (txAttr != null) { return txAttr; } // Last fallback is the class of the original method. txAttr = findTransactionAttribute(method.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } } ​ return null; }

最终来到SpringTransactionAnnotationParser#parseTransactionAnnotation()

 

kotlin

复制代码

​ @Override public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {   //这里就是分析Method是否被@Transactional注解标注,有的话,不用说BeanFactoryTransactionAttributeSourceAdvisor适配当前bean,进行代理,并且注入切点   //BeanFactoryTransactionAttributeSourceAdvisor   AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);   if (attributes != null) {     return parseTransactionAnnotation(attributes);   }   else {     return null;   } }

上面就是判断是否需要根据@Transactional进行代理对象创建的判断过程。@Transactional的作用就是标识方法需要被代理,同时携带事务管理需要的属性信息。

3.2.2 如何进行事务控制

在之前Spring切面编程实现原理一文中我碍于文章篇幅只分析了JDK代理的实现方式,但在 SpringBoot 2.x AOP中会默认使用Cglib来实现,所以今天就来分析一下CGLIB这种方式。

Spring的CGLIB方式生存代理对象是靠ObjenesisCglibAopProxy完成的,ObjenesisCglibAopProxy继承自CglibAopProxy,调用方法#createProxyClassAndInstance()得到基于Cglib动态代理的对象。最终的代理对象的代理方法DynamicAdvisedInterceptor#intercept()方法

 

ini

复制代码

@Override @Nullable public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; Object target = null; TargetSource targetSource = this.advised.getTargetSource(); try { if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool... target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // Check whether we only have one InvokerInterceptor: that is, // no real advice, but just reflective invocation of the target. if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) { // We can skip creating a MethodInvocation: just invoke the target directly. // Note that the final invoker must be an InvokerInterceptor, so we know // it does nothing but a reflective operation on the target, and no hot // swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); try { retVal = methodProxy.invoke(target, argsToUse); } catch (CodeGenerationException ex) { CglibMethodInvocation.logFastClassGenerationFailure(method); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } } else { // We need to create a method invocation... retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }

这和以JDK实现的动态代理JdkDynamicAopProxy实现了InvocationHandler执行invoke()来进行逻辑增强套路是一样的。

通过分析 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)返回的是TransactionInterceptor,然后来到new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(),最终调用TransactionInterceptor#invoke()方法

 

less

复制代码

@Override @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); ​ // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }

#invokeWithinTransaction()就是通过切面实现事务控制的核心逻辑所在:

 

java

复制代码

@Nullable protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,   final InvocationCallback invocation) throws Throwable { ​    TransactionAttributeSource tas = getTransactionAttributeSource();  final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);  final TransactionManager tm = determineTransactionManager(txAttr); ​  //省略部分代码                //获取事物管理器  PlatformTransactionManager ptm = asPlatformTransactionManager(tm);  final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); ​  if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {   // 打开事务(内部就是getTransactionStatus的过程)   TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification); ​   Object retVal;   try {    // 执行业务逻辑 invocation.proceedWithInvocation();   }   catch (Throwable ex) {    // 异常回滚    completeTransactionAfterThrowing(txInfo, ex);    throw ex;   }   finally {    cleanupTransactionInfo(txInfo);   } ​   //省略部分代码                        //提交事物   commitTransactionAfterReturning(txInfo);   return retVal; }

4.总结

行文至此,Spring基于AOP自动完成事务控制的逻辑分析就完结了。Spring的声明式事务注解开发非常简单,只需要在方法上加上注解@Transactional,Spring就可以自动帮我们进行事务的开启、提交、回滚操作。但是在日常开发中却经常出现事务失效的情况,所以了解Spring事务控制实现还是很有必要的,同时还可以加深对Spring AOP应用的认识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SpringAOP和IOC实现原理AOP(面向切面编程)是Spring框架的一个重要特性,它通过在运行时动态地将代码切入到类的方法中,实现了对业务逻辑的解耦和横向切割。SpringAOP实现原理是基于动态代理和字节码生成技术,通过在运行时动态地生成代理对象,将切面逻辑织入到目标对象的方法中。 IOC(控制反转)是Spring框架的另一个重要特性,它通过将对象的创建和依赖关系的管理交给Spring容器来实现,从而实现了对象之间的解耦和灵活性。Spring的IOC实现原理是基于反射和XML配置文件,通过读取配置文件中的信息,动态地创建对象并注入依赖关系,从而实现了对象的管理和控制。 ### 回答2: Spring框架作为Java企业应用中广泛使用的开发框架,其内部实现的AOP和IOC功能是其较为重要的组成部分。AOP(面向切面编程)和IOC(控制反转)是两个不同的概念,但它们之间存在紧密联系。在回答任何一个问题之前,需要更深入地了解这些术语以及它们的目的。 首先,了解AOP实现原理AOP的主要原理是将整个应用程序分解成特定的相关部分,并标识出这些部分的职责。然后,AOP框架将横切关注点(Crosscutting Concerns)划分为一个个切面(Aspect),并实现将目标对象在运行时交织上这些切面的功能。这个交织的过程称为织入(Weaving),这样应用程序中的某些功能可以在运行时动态地添加到对象中,而无需对其进行静态编码。在Spring框架中,主流的AOP实现采用代理模式(Proxy)。它将目标对象和切面运作在代理对象之间,代理对象则在运行时插入切面功能。 其次,了解IOC的实现原理控制反转是指将对象间的依赖关系的控制权从目标对象自身转移到容器中管理,从而实现对象的松耦合。Spring框架是典型的IOC容器,它利用依赖注入(Dependency Injection)技术,通过在配置文件(XML或JavaConfig)中定义对象之间的依赖关系,在容器中实例化对象并完成之间的依赖注入。在依赖注入中,容器将对象之间的依赖关系检测到,并自动为其中的依赖添加实例。这样,程序员就不需要在代码中显式地将对象之间的依赖关系硬编码,而可以通过注解、XML配置文件或JavaConfig等方式来管理这些对象。 综上所述,AOP和IOC是Spring框架的核心概念之一。通过使用Spring框架的AOP和IOC功能,开发人员可以编写更简洁、高效的代码,并更容易地实现面向对象编程的最佳实践。 ### 回答3: SpringAOP和IOC(控制反转)是Spring框架中非常重要的两个部分,能够让开发人员更好的实现面向切面编程和解耦,提高代码可维护性和灵活性。 首先,让我们来看看Spring的IOC实现原理Spring的IOC是控制反转的实现,即通过容器管理对象之间的依赖关系,而不是在代码中直接通过new关键词来创建对象。Spring的IOC实现的核心思想是依赖注入(Dependency Injection,DI),即对象通过Setter、构造函数、注解等方式获取它所需要的依赖对象。通过Spring容器来管理和维护所有应用程序需要的对象实例和依赖关系。在实现IOC的时候,Spring会通过配置文件或者注解方式把对象的创建、初始化和依赖注入关系都详细地描述出来,然后在运行时,通过反射机制自动创建对象,再将依赖注入进去,以此实现对象的控制权转由Spring容器来掌控。这样的实现可以减轻程序员的工作负担,提高程序的复用性和扩展性。 其次,SpringAOP实现原理也是很重要的。AOP可以让程序员将一些横切逻辑和业务处理逻辑分离出来,达到代码解耦的目的。在Spring中,AOP使用代理(Proxy)的方式实现,通过对需要执行的目标方法进行拦截,并在目标方法执行前后执行额外的逻辑,如开启/关闭事务、安全认证、日志记录等。代理类可以使用JDK自带的动态代理机制或CGLIB等第三方代理框架来生成,而切面对象则负责维护切面所需要拦截的目标对象、目标方法、切面执行顺序等信息。SpringAOP框架为切面提供丰富的表达式语言来指定需要拦截的方法,如通配符、正则表达式和AspectJ注解等。 因此,SpringAOP和IOC实现原理都是非常重要的,它们的实现可以让应用程序代码更灵活、更容易维护,同时也使得程序员的工作更加高效。但是需要注意的是,在使用SpringAOP和IOC时,要注意配置的正确性和合理性,否则可能会带来一些潜在的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值