`
jiwenke
  • 浏览: 402908 次
  • 性别: Icon_minigender_1
  • 来自: 南京
博客专栏
4ee69929-b8e1-3eb5-bbca-157d075d6192
Spring技术内幕——深...
浏览量:183336
D1c226f7-74e9-3ec4-a15b-18a45ccd88c5
随笔:Spring与云计算...
浏览量:26806
社区版块
存档分类
最新评论

Spring源代码解析(六):Spring声明式事务处理

阅读更多
我们看看Spring中的事务处理的代码,使用Spring管理事务有声明式和编程式两种方式,声明式事务处理通过AOP的实现把事物管理代码作为方面封装来横向插入到业务代码中,使得事务管理代码和业务代码解藕。在这种方式我们结合IoC容器和Spirng已有的FactoryBean来对事务管理进行属性配置,比如传播行为,隔离级别等。其中最简单的方式就是通过配置TransactionProxyFactoryBean来实现声明式事物;
在整个源代码分析中,我们可以大致可以看到Spring实现声明式事物管理有这么几个部分:

    * 对在上下文中配置的属性的处理,这里涉及的类是TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性信息放在TransactionAttribute中来使用,而这些属性的处理往往是和对切入点的处理是结合起来的。对属性的处理放在类TransactionAttributeSource中完成。
    * 创建事物的过程,这个过程是委托给具体的事物管理器来创建的,但Spring通过TransactionStatus来传递相关的信息。
    * 对事物的处理通过对相关信息的判断来委托给具体的事物管理器完成。

我们下面看看具体的实现,在TransactionFactoryBean中:
public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
        implements FactoryBean, BeanFactoryAware {
//这里是Spring事务处理而使用的AOP拦截器,中间封装了Spring对事务处理的代码来支持声明式事务处理的实现
    private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();

    private Pointcut pointcut;

//这里Spring把TransactionManager注入到TransactionInterceptor中去
    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionInterceptor.setTransactionManager(transactionManager);
    }

//这里把在bean配置文件中读到的事务管理的属性信息注入到TransactionInterceptor中去
    public void setTransactionAttributes(Properties transactionAttributes) {
        this.transactionInterceptor.setTransactionAttributes(transactionAttributes);
    }

    .........中间省略了其他一些方法.......

    //这里创建Spring AOP对事务处理的Advisor
    protected Object createMainInterceptor() {
        this.transactionInterceptor.afterPropertiesSet();
        if (this.pointcut != null) {
            //这里使用默认的通知器
            return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
        }
        else {
            // 使用上面定义好的TransactionInterceptor作为拦截器,同时使用TransactionAttributeSourceAdvisor
            return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
        }
    }
}

那什么时候Spring的TransactionInterceptor被注入到Spring AOP中成为Advisor中的一部分呢?我们看到在TransactionProxyFactoryBean中,这个方法在IOC初始化bean的时候被执行:
    public void afterPropertiesSet() {
        .......
        //TransactionProxyFactoryBean实际上使用ProxyFactory完成AOP的基本功能。
        ProxyFactory proxyFactory = new ProxyFactory();

        if (this.preInterceptors != null) {
            for (int i = 0; i < this.preInterceptors.length; i++) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptors[i]));
            }
        }

        //这里是Spring加入通知器的地方
        //有两种通知器可以被加入DefaultPointcutAdvisor或者TransactionAttributeSourceAdvisor
        //这里把Spring处理声明式事务处理的AOP代码都放到ProxyFactory中去,怎样加入advisor我们可以参考ProxyFactory的父类AdvisedSupport()
        //由它来维护一个advice的链表,通过这个链表的增删改来抽象我们对整个通知器配置的增删改操作。
        proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

        if (this.postInterceptors != null) {
            for (int i = 0; i < this.postInterceptors.length; i++) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.postInterceptors[i]));
            }
        }

        proxyFactory.copyFrom(this);
       
        //这里创建AOP的目标源
        TargetSource targetSource = createTargetSource(this.target);
        proxyFactory.setTargetSource(targetSource);

        if (this.proxyInterfaces != null) {
            proxyFactory.setInterfaces(this.proxyInterfaces);
        }
        else if (!isProxyTargetClass()) {
            proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass()));
        }

        this.proxy = getProxy(proxyFactory);
    }

Spring 已经定义了一个transctionInterceptor作为拦截器或者AOP advice的实现,在IOC容器中定义的其他属性比如transactionManager和事务管理的属性都会传到已经定义好的 TransactionInterceptor那里去进行处理。以上反映了基本的Spring AOP的定义过程,其中pointcut和advice都已经定义好,同时也通过通知器配置到ProxyFactory中去了。
下面让我们回到TransactionProxyFactoryBean中看看TransactionAttributeSourceAdvisor是怎样定义的,这样我们可以理解具体的属性是怎样起作用,这里我们分析一下类TransactionAttributeSourceAdvisor:
public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {
    //和其他Advisor一样,同样需要定义AOP中的用到的Interceptor和Pointcut
    //Interceptor使用传进来的TransactionInterceptor
    //而对于pointcut,这里定义了一个内部类,参见下面的代码  
    private TransactionInterceptor transactionInterceptor;

    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut();
   
    .........
    //定义的PointCut内部类
        private class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
       .......
      //方法匹配的实现,使用了TransactionAttributeSource类
        public boolean matches(Method method, Class targetClass) {
            TransactionAttributeSource tas = getTransactionAttributeSource();
            //这里使用TransactionAttributeSource来对配置属性进行处理
            return (tas != null && tas.getTransactionAttribute(method, targetClass) != null);
        }
    ........省略了equal,hashcode,tostring的代码
    }

这里我们看看属性值是怎样被读入的:AbstractFallbackTransactionAttributeSource负责具体的属性读入任务,我们可以有两种读入方式,比如annotation和直接配置.我们下面看看直接配置的读入方式,在Spring中同时对读入的属性值进行了缓存处理,这是一个decorator模式:
    public final TransactionAttribute getTransactionAttribute(Method method, Class targetClass) {
        //这里先查一下缓存里有没有事务管理的属性配置,如果有从缓存中取得TransactionAttribute
        Object cacheKey = getCacheKey(method, targetClass);
        Object cached = this.cache.get(cacheKey);
        if (cached != null) {
            if (cached == NULL_TRANSACTION_ATTRIBUTE) {
                return null;
            }
            else {
                return (TransactionAttribute) cached;
            }
        }
        else {
            // 这里通过对方法和目标对象的信息来计算事务缓存属性
            TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
            //把得到的事务缓存属性存到缓存中,下次可以直接从缓存中取得。
            if (txAtt == null) {
                this.cache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
            }
            else {
                ...........
                this.cache.put(cacheKey, txAtt);
            }
            return txAtt;
        }
    }

别急,基本的处理在computeTransactionAttribute()中:
    private TransactionAttribute computeTransactionAttribute(Method method, Class targetClass) {
        //这里检测是不是public方法
        if(allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        }
       
        Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
       
        // First try is the method in the target class.
        TransactionAttribute txAtt = findTransactionAttribute(findAllAttributes(specificMethod));
        if (txAtt != null) {
            return txAtt;
        }

        // Second try is the transaction attribute on the target class.
        txAtt = findTransactionAttribute(findAllAttributes(specificMethod.getDeclaringClass()));
        if (txAtt != null) {
            return txAtt;
        }

        if (specificMethod != method) {
            // Fallback is to look at the original method.
            txAtt = findTransactionAttribute(findAllAttributes(method));
            if (txAtt != null) {
                return txAtt;
            }
            // Last fallback is the class of the original method.
            return findTransactionAttribute(findAllAttributes(method.getDeclaringClass()));
        }
        return null;
    }

经过一系列的尝试我们可以通过findTransactionAttribute()通过调用findAllAttribute()得到TransactionAttribute的对象,如果返回的是null,这说明该方法不是我们需要事务处理的方法。
在完成把需要的通知器加到ProxyFactory中去的基础上,我们看看具体的看事务处理代码怎样起作用,在TransactionInterceptor中:
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        //这里得到目标对象
        Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);

        //这里同样的通过判断是否能够得到TransactionAttribute来决定是否对当前方法进行事务处理,有可能该属性已经被缓存,
        //具体可以参考上面对getTransactionAttribute的分析,同样是通过TransactionAttributeSource
        final TransactionAttribute txAttr =
                getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
        final String joinpointIdentification = methodIdentification(invocation.getMethod());

        //这里判断我们使用了什么TransactionManager
        if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {
            // 这里创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去
            TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);
            Object retVal = null;
            try {
                  retVal = invocation.proceed();
            }
            catch (Throwable ex) {
                // target invocation exception
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                cleanupTransactionInfo(txInfo);
            }
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }

        else {
            // 使用的是Spring定义的PlatformTransactionManager同时实现了回调接口,我们通过其回调函数完成事务处理,就像我们使用编程式事务处理一样。
            try {
                Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,
                        new TransactionCallback() {
                            public Object doInTransaction(TransactionStatus status) {
                                //同样的需要一个TransactonInfo
                                TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);
                                try {
                                    return invocation.proceed();
                                }
                             .....这里省去了异常处理和事务信息的清理代码
                        });
             ...........
        }
    }

这里面涉及到事务的创建,我们可以在TransactionAspectSupport实现的事务管理代码:
    protected TransactionInfo createTransactionIfNecessary(
            TransactionAttribute txAttr, final String joinpointIdentification) {

        // If no name specified, apply method identification as transaction name.
        if (txAttr != null && txAttr.getName() == null) {
            txAttr = new DelegatingTransactionAttribute(txAttr) {
                public String getName() {
                    return joinpointIdentification;
                }
            };
        }

        TransactionStatus status = null;
        if (txAttr != null) {
        //这里使用了我们定义好的事务配置信息,有事务管理器来创建事务,同时返回TransactionInfo
            status = getTransactionManager().getTransaction(txAttr);
        }
        return prepareTransactionInfo(txAttr, joinpointIdentification, status);
    }

首先通过TransactionManager得到需要的事务,事务的创建根据我们定义的事务配置决定,在 AbstractTransactionManager中给出一个标准的创建过程,当然创建什么样的事务还是需要具体的 PlatformTransactionManager来决定,但这里给出了创建事务的模板:
    public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        Object transaction = doGetTransaction();
        ......

        if (definition == null) {
            //如果事务信息没有被配置,我们使用Spring默认的配置方式
            definition = new DefaultTransactionDefinition();
        }

        if (isExistingTransaction(transaction)) {
            // Existing transaction found -> check propagation behavior to find out how to behave.
            return handleExistingTransaction(definition, transaction, debugEnabled);
        }

        // Check definition settings for new transaction.
        //下面就是使用配置信息来创建我们需要的事务;比如传播属性和同步属性等
        //最后把创建过程中的信息收集起来放到TransactionStatus中返回;  
        if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
            throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
        }

        // No existing transaction found -> check propagation behavior to find out how to behave.
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException(
                    "Transaction propagation 'mandatory' but no existing transaction found");
        }
        else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            //这里是事务管理器创建事务的地方,并将创建过程中得到的信息放到TransactionStatus中去,包括创建出来的事务
            doBegin(transaction, definition);
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
        }
        else {
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);
        }
    }

接着通过调用prepareTransactionInfo完成事务创建的准备,创建过程中得到的信息存储在TransactionInfo对象中进行传递同时把信息和当前线程绑定;
    protected TransactionInfo prepareTransactionInfo(
            TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {

        TransactionInfo txInfo = new TransactionInfo(txAttr, joinpointIdentification);
        if (txAttr != null) {
        .....
            // 同样的需要把在getTransaction中得到的TransactionStatus放到TransactionInfo中来。
            txInfo.newTransactionStatus(status);
        }
        else {
        .......
       }

        // 绑定事务创建信息到当前线程
        txInfo.bindToThread();
        return txInfo;
    }

将创建事务的信息返回,然后看到其他的事务管理代码:
    protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
        if (txInfo != null && txInfo.hasTransaction()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking commit for transaction on " + txInfo.getJoinpointIdentification());
            }
            this.transactionManager.commit(txInfo.getTransactionStatus());
        }
    }

通过transactionManager对事务进行处理,包括异常抛出和正常的提交事务,具体的事务管理器由用户程序设定。
    protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
        if (txInfo != null && txInfo.hasTransaction()) {
            if (txInfo.transactionAttribute.rollbackOn(ex)) {
                ......
                try {
                    this.transactionManager.rollback(txInfo.getTransactionStatus());
                }
                ..........
      }
            else {
                .........
                try {
                    this.transactionManager.commit(txInfo.getTransactionStatus());
                }
       ...........
    }

    protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
        if (txInfo != null && txInfo.hasTransaction()) {
            ......
            this.transactionManager.commit(txInfo.getTransactionStatus());
        }
    }

Spring通过以上代码对transactionManager进行事务处理的过程进行了AOP包装,到这里我们看到为了方便客户实现声明式的事务处理,Spring还是做了许多工作的。如果说使用编程式事务处理,过程其实比较清楚,我们可以参考书中的例子:
    TransactionDefinition td = new DefaultTransactionDefinition();
    TransactionStatus status = transactionManager.getTransaction(td);
    try{
          ......//这里是我们的业务方法
    }catch (ApplicationException e) {
       transactionManager.rollback(status);
       throw e
    }
    transactionManager.commit(status);
     ........

我们看到这里选取了默认的事务配置DefaultTransactionDefinition,同时在创建事物的过程中得到TransactionStatus,然后通过直接调用事务管理器的相关方法就能完成事务处理。
声明式事务处理也同样实现了类似的过程,只是因为采用了声明的方法,需要增加对属性的读取处理,并且需要把整个过程整合到Spring AOP框架中和IoC容器中去的过程。
下面我们选取一个具体的transactionManager - DataSourceTransactionManager来看看其中事务处理的实现:
同样的通过使用AbstractPlatformTransactionManager使用模板方法,这些都体现了对具体平台相关的事务管理器操作的封装,比如commit:
    public final void commit(TransactionStatus status) throws TransactionException {
        ......
        DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
        if (defStatus.isLocalRollbackOnly()) {
            ......
            processRollback(defStatus);
            return;
        }
             .......
            processRollback(defStatus);
        ......
        }

        processCommit(defStatus);
    }

通过对TransactionStatus的具体状态的判断,来决定具体的事务处理:
    private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        try {
            boolean beforeCompletionInvoked = false;
            try {
                triggerBeforeCommit(status);
                triggerBeforeCompletion(status);
                beforeCompletionInvoked = true;
                boolean globalRollbackOnly = false;
                if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
                    globalRollbackOnly = status.isGlobalRollbackOnly();
                }
                if (status.hasSavepoint()) {
                ........
                   status.releaseHeldSavepoint();
                }
                else if (status.isNewTransaction()) {
                ......
                    doCommit(status);
                }
            .........
    }

这些模板方法的实现由具体的transactionManager来实现,比如在DataSourceTransactionManager:
    protected void doCommit(DefaultTransactionStatus status) {
        //这里得到存在TransactionInfo中已经创建好的事务
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();

        //这里得到和事务绑定的数据库连接
        Connection con = txObject.getConnectionHolder().getConnection();
        ........
        try {
        //这里通过数据库连接来提交事务
            con.commit();
        }
       .......
    }

    protected void doRollback(DefaultTransactionStatus status) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
        Connection con = txObject.getConnectionHolder().getConnection();
        if (status.isDebug()) {
            logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
        }
        try {
        //这里通过数据库连接来回滚事务
            con.rollback();
        }
        catch (SQLException ex) {
            throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
        }
    }

我们看到在DataSourceTransactionManager中最后还是交给connection来实现事务的提交和rollback。整个声明式事务处理是事务处理在Spring AOP中的应用,我们看到了一个很好的使用Spring AOP的例子,在Spring声明式事务处理的源代码中我们可以看到:
1.怎样封装各种不同平台下的事务处理代码
2.怎样读取属性值和结合事务处理代码来完成既定的事务处理策略
3.怎样灵活的使用SpringAOP框架。
如果能够结合前面的Spring AOP的源代码来学习,理解可能会更深刻些。
分享到:
评论
5 楼 faith789510 2016-01-13  
TransactionProxyFactoryBean 什么情况下,什么时候起作用,在xml里面没有配置
4 楼 bennyparlo 2007-09-28  
好久没来回帖了,由于最近正好在工作作用使用到了spring的事务管理,所以我也来总结下

spring已经提供了声明式的事务管理模型,这主要借用了基于ioc容器实现的aop编程框架,利用类似拦截器的方式将定义需要进行事务处理的bean方法进行代理封装.

当然其核心部分还在于其自身实现的事务管理,因此这里就从编程式的事务管理开始讲起.

首先,对于事务的定义可以通过TransactionDefinition接口的实现来进行描述,当然spring已经提供了最常用的DefaultTransactionDefinition实现.这个设计的思想又不禁让人想起了ioc容器中用到的BeanDefinition以及其默认实现DefaultBeanDefinition.这样设计的主要目的在于将定义的描述对象与其每个实例进行隔离.

而对于被创建的事务对象将通过TransactionStatus来进行封装,当然该接口也有继承于AbstractTransactionStatus的默认实现DefaultTransactionStatus.因此在1个事务方法中,事务管理器将根据TransactionStatus的实例对象进行commit,rollback等操作.但这里值得1提的是,如果以
DefaultTransactionStatus为例,该类中封装了private final Object transaction对象.这里的transaction在运行期将是个SmartTransactionObject的实现对象,如JdbcTransactionObjectSupport或者DataSourceTransactionObject或者JtaTransactionObject,当然这里的DataSourceTransactionObject是个内部类,它继承了DataSourceTransactionObjectSupport.

再以DataSourceTransactionObject为例,在该类的父类DataSourceTransactionObjectSupport中,封装了private ConnectionHolder connectionHolder,而该connectionHolder对象又绑定了private Connection currentConnection.这里其实是事务实现的核心所在了,在接下来的讲述中会发现,jdbc事务的最终操作其实就委托给currentConnection来做进行相应的处理.
3 楼 jiwenke 2007-06-23  
autumnxian 写道
文章太长了,能不能概括一下有哪几个类的代码是重点?

大概总结一下,可以关注这几个类的实现:
TransactionInterceptor - 是使用AOP实现声明式事务处理的拦截器,封装了Spring对声明式事务处理的实现。
TransactionAttributeSource和TransactionAttribute - 这里封装对声明式事务处理属性的识别,信息的读入和配置
TransactionInfo ,TransactionStatus - 这是事务处理信息存放的主要地方,而且是和线程绑定的。
然后就是TransactionManager, 通过使用TransactionInfo和TransactionStatus来控制事务处理 - 中间的一些和具体事务处理器无关的操作封装到AbstractPlatformTransactionManager里面实现了。
对编程式的事务处理TransactionDefinition是定义事务属性的类,Spring提供了DefaultTransactionDefinition供用户使用。
2 楼 autumnxian 2007-06-21  
文章太长了,能不能概括一下有哪几个类的代码是重点?
1 楼 jiwenke 2007-06-10  
这几天把贴子重新更新了一遍,发现很多错误和思路上不清楚的地方,欢迎拍砖,我会继续更新贴子的。

相关推荐

    查看进程信息,方便排查问题

    查看进程信息,方便排查问题

    IDA Pro分析STM32F1xx插件

    IDA Pro分析STM32F1xx插件

    基于SSH的线上医疗报销系统.zip-毕设&课设&实训&大作业&竞赛&项目

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    matlab的小型的微电网仿真模型文件

    小型的微电网仿真模型,简单模拟了光伏,家庭负载变化的使用情况

    MATLAB代码实现:分布式电源接入对配电网运行影响深度分析与评估,MATLAB代码分析:分布式电源接入对配电网运行影响评估,MATLAB代码:分布式电源接入对配电网影响分析 关键词:分布式电源 配电

    MATLAB代码实现:分布式电源接入对配电网运行影响深度分析与评估,MATLAB代码分析:分布式电源接入对配电网运行影响评估,MATLAB代码:分布式电源接入对配电网影响分析 关键词:分布式电源 配电网 评估 参考文档:《自写文档,联系我看》参考选址定容模型部分; 仿真平台:MATLAB 主要内容:代码主要做的是分布式电源接入场景下对配电网运行影响的分析,其中,可以自己设置分布式电源接入配电网的位置,接入配电网的有功功率以及无功功率的大小,通过牛顿拉夫逊法求解分布式电源接入后的电网潮流,从而评价分布式电源接入前后的电压、线路潮流等参数是否发生变化,评估配电网的运行方式。 代码非常精品,是研究含分布式电源接入的电网潮流计算的必备程序 ,分布式电源; 配电网; 接入影响分析; 潮流计算; 牛顿拉夫逊法; 电压评估; 必备程序。,基于MATLAB的分布式电源对配电网影响评估系统

    基于Unity-Bolt开发的游戏demo.zip

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    重庆市农村信用合作社 农商行数字银行系统建设方案.ppt

    重庆市农村信用合作社 农商行数字银行系统建设方案.ppt

    光伏并网逆变器设计方案与高效实现:结合matlab电路仿真、DSP代码及环流抑制策略,光伏并网逆变器设计方案:结合matlab电路文件与DSP程序代码,实现高效并联环流抑制策略,光伏并网逆变器设计方案

    光伏并网逆变器设计方案与高效实现:结合matlab电路仿真、DSP代码及环流抑制策略,光伏并网逆变器设计方案:结合matlab电路文件与DSP程序代码,实现高效并联环流抑制策略,光伏并网逆变器设计方案,附有相关的matlab电路文件,以及DSP的程序代码,方案、仿真文件、代码三者结合使用效果好,事半功倍。 备注:赠送逆变器并联环流matlab文件,基于矢量控制的环流抑制策略和下垂控制的环流抑制 ,光伏并网逆变器设计方案; MATLAB电路文件; DSP程序代码; 方案、仿真文件、代码结合使用; 并联环流抑制策略; 下垂控制的环流抑制,光伏并网逆变器优化设计:方案、仿真与DSP程序代码三合一,并赠送并联环流抑制策略Matlab文件

    Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入分类预测(含模型描述及示例代码)

    内容概要:本文介绍了通过 Matlab 实现鲸鱼优化算法(WOA)与门控循环单元(GRU)结合的多输入分类预测模型。文章首先概述了时间序列预测的传统方法局限性以及引入 WOA 的优势。然后,重点阐述了项目背景、目标、挑战及其独特之处。通过详细介绍数据预处理、模型构建、训练和评估步骤,最终展示了模型的效果预测图及应用实例。特别强调利用 WOA 改善 GRU 的参数设置,提高了多输入时间序列预测的准确性与鲁棒性。 适合人群:对时间序列分析有兴趣的研究者,从事金融、能源、制造业等行业数据分析的专业人士,具备一定的机器学习基础知识和技术经验。 使用场景及目标:本项目旨在开发一个高度准确和稳定的多变量时间序列预测工具,能够用于金融市场预测、能源需求规划、生产调度优化等领域,为企业和个人提供科学决策依据。 其他说明:项目提供的源代码和详细的开发指南有助于学习者快速掌握相关技能,并可根据实际需求调整模型参数以适应不同的业务情境。

    基于vue+elment-ui+node.js的后台管理系统 .zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    Python 实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost多输入分类预测(含模型描述及示例代码)

    内容概要:本文介绍了Python中基于双向长短期记忆网络(BiLSTM)与AdaBoost相结合的多输入分类预测模型的设计与实现。BiLSTM擅长捕捉时间序列的双向依赖关系,而AdaBoost则通过集成弱学习器来提高分类精度和稳定性。文章详述了该项目的背景、目标、挑战、特色和应用场景,并提供了详细的模型构建流程、超参数优化以及视觉展示的方法和技术要点。此外,还附有完整的效果预测图表程序和具体示例代码,使读者可以快速上手构建属于自己的高效稳定的时间序列预测系统。 适合人群:对深度学习特别是时序数据分析感兴趣的开发者或者科研工作者;正在探索高级机器学习技术和寻求解决方案的企业分析师。 使用场景及目标:适用于希望提升时间序列或多输入数据类别判定准确度的业务情境,比如金融市场的走势预估、医学图像分析中的病变区域判读或是物联网环境监测下设备状态预警等任务。目的是为了创建更加智能且可靠的预测工具,在实际应用中带来更精准可靠的结果。 其他说明:文中提供的所有Python代码片段和方法都可以直接运用于实践中,并可根据特定的问题进行相应调整和扩展,进一步改进现有系统的效能并拓展新的功能特性。

    maven-script-interpreter-javadoc-1.0-7.el7.x64-86.rpm.tar.gz

    1、文件内容:maven-script-interpreter-javadoc-1.0-7.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/maven-script-interpreter-javadoc-1.0-7.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊

    在云服务器上搭建MQTT服务器(超详细,一步到位)

    在云服务器上搭建MQTT服务器(超详细,一步到位)

    复现改进的L-SHADE差分进化算法求解最优化问题详解:附MATLAB源码与测试函数集,复现改进的L-SHADE差分进化算法求解最优化问题详解:MATLAB源码与测试集全攻略,复现改进的L-SHADE

    复现改进的L-SHADE差分进化算法求解最优化问题详解:附MATLAB源码与测试函数集,复现改进的L-SHADE差分进化算法求解最优化问题详解:MATLAB源码与测试集全攻略,复现改进的L-SHADE差分进化算法求最优化问题 对配套文献所提出的改进的L-SHADE差分进化算法求解最优化问题的的复现,提供完整MATLAB源代码和测试函数集,到手可运行,运行效果如图2所示。 代码所用测试函数集与文献相同:对CEC2014最优化测试函数集中的全部30个函数进行了测试验证,运行结果与文献一致。 ,复现; 改进的L-SHADE差分进化算法; 最优化问题求解; MATLAB源代码; 测试函数集; CEC2014最优化测试函数集,复现改进L-SHADE算法:最优化问题的MATLAB求解与验证

    天津大学:深度解读DeepSeek原理与效应.pdf

    天津大学:深度解读DeepSeek原理与效应.pdf 1.大语言模型发展路线图 2.DeepSeek V2-V3/R1技术原理 3DeepSeek效应 4.未来展望

    光伏混合储能微电网能量管理系统模型:基于MPPT控制的光伏发电与一阶低通滤波算法的混合储能系统优化管理,光伏混合储能微电网能量优化管理与稳定运行系统,光伏-混合储能微电网能量管理系统模型

    光伏混合储能微电网能量管理系统模型:基于MPPT控制的光伏发电与一阶低通滤波算法的混合储能系统优化管理,光伏混合储能微电网能量优化管理与稳定运行系统,光伏-混合储能微电网能量管理系统模型 系统主要由光伏发电模块、mppt控制模块、混合储能系统模块、直流负载模块、soc限值管理控制模块、hess能量管理控制模块。 光伏发电系统采用mppt最大跟踪控制,实现光伏功率的稳定输出;混合储能系统由蓄电池和超级电容组合构成,并采用一阶低通滤波算法实现两种储能介质间的功率分配,其中蓄电池响应目标功率中的低频部分,超级电容响应目标功率中的高频部分,最终实现对目标功率的跟踪响应;SOC限值管理控制,根据储能介质的不同特性,优化混合储能功率分配,进一步优化蓄电池充放电过程,再根据超级电容容量特点,设计其荷电状态区分管理策略,避免过充过放,维持系统稳定运行;最后,综合混合储能和系统功率平衡,针对光伏储能微电网的不同工况进行仿真实验,验证控制策略的有效性。 本模型完整无错,附带对应复现文献paper,容易理解,可塑性高 ,光伏; 混合储能系统; 能量管理; MPPT控制; 直流负载;

    Matlab算法下的A星路径规划改进版:提升搜索效率,优化拐角并路径平滑处理,Matlab下的A星算法改进:提升搜索效率、冗余拐角优化及路径平滑处理,Matlab算法代码 A星算法 路径规划A* As

    Matlab算法下的A星路径规划改进版:提升搜索效率,优化拐角并路径平滑处理,Matlab下的A星算法改进:提升搜索效率、冗余拐角优化及路径平滑处理,Matlab算法代码 A星算法 路径规划A* Astar算法仿真 传统A*+改进后的A*算法 Matlab代码 改进: ①提升搜索效率(引入权重系数) ②冗余拐角优化(可显示拐角优化次数) ③路径平滑处理(引入梯度下降算法配合S-G滤波器) ,Matlab算法代码; A星算法; 路径规划A*; Astar算法仿真; 传统A*; 改进A*算法; 提升搜索效率; 冗余拐角优化; 路径平滑处理; 权重系数; S-G滤波器。,Matlab中的A*算法:传统与改进的路径规划仿真研究

    探索与Cursor协作创建一个完整的前后端分离的项目的最佳实践,提示词指南

    项目开发所用的主要提示词模板

    基于OpenVINO.NET实现的人脸检测。.zip

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    电力系统暂态稳定性仿真分析:Matlab编程与Simulink模型下的各类故障影响研究,电力系统暂态稳定性仿真分析:Matlab编程与Simulink模型下的各类故障影响研究,电力系统暂态稳定性Mat

    电力系统暂态稳定性仿真分析:Matlab编程与Simulink模型下的各类故障影响研究,电力系统暂态稳定性仿真分析:Matlab编程与Simulink模型下的各类故障影响研究,电力系统暂态稳定性Matlab编程 Simulink仿真 单机无穷大系统发生各类(三相短路,单相接地,两相接地,两相相间短路)等短路故障,各类(单相断线,两相断线,三相断线)等断线故障,暂态稳定仿真分析 Simulink搭建电力系统暂态仿真模型 通过仿真,观察串联电抗器,并联补偿器,自动重合闸,以及故障切除快慢对暂态稳定性的影响 ,电力系统暂态稳定性; Matlab编程; Simulink仿真; 短路故障; 断线故障; 暂态稳定仿真分析; 仿真模型搭建; 电抗器影响; 补偿器影响; 自动重合闸; 故障切除时间。,Matlab编程与Simulink仿真在电力系统暂态稳定性分析中的应用

Global site tag (gtag.js) - Google Analytics