Skip to content
PYD ENTERPRISES

Migration guide

Spring XML to Spring Boot: find the business logic hiding in AOP and wiring

Moving Spring XML to @Configuration looks mechanical until an aspect turns out to apply a discount. This guide shows how to inventory wiring, transactions, aspects and properties before you convert any of it.

Spring XMLSpring Boot
DIFFICULTY
Moderate
OUTPUT
OpenAPI / YAML
SYNTAX TRAPS
5 covered
WORKFLOW
6 steps

By Pranav Kulkarni, Head of Language Engineering · Updated 15 Oct 2026

Technical syntax challenges

Where Spring XML migrations go wrong.

01

AOP pointcuts apply logic by pattern

execution(* com.example.pricing..*Service.*(..)) matches every method of every class ending in Service under that package, including classes added years later. An around advice on that pointcut runs on all of them. If the advice changes a return value, it is a business rule applied by naming convention.

02

tx:advice method patterns

<tx:method name="get*" read-only="true"/> and <tx:method name="*" rollback-for="..."/> set transaction semantics by method name. A method renamed from getQuote to quote silently loses read-only, and converting to @Transactional needs the effective setting per method, not per pattern.

03

Property references across environments

${pricing.maxDiscount:15} resolves from properties files that differ per environment, with a default in the XML. Spring Boot's application.yml, profiles and @ConfigurationProperties need the full matrix of values, including environments where the default is the one in effect.

04

Parent beans, scopes and autowiring

Abstract parent bean definitions, scope="prototype", lazy-init and autowire="byName" change what gets injected where. The effective object graph, not the XML text, is what the new configuration must reproduce.

05

XML spread across jars

<import resource="classpath*:META-INF/spring/*.xml"/> pulls definitions from every jar on the classpath, and later definitions override earlier ones with the same id. Bean overriding is disabled by default in Spring Boot 2.1 and later, so overrides must be found and resolved deliberately.

Extraction workflow

6 steps from source to signed-off spec.

The sequence a PYD ENTERPRISES Discovery Scan runs for this stack. Every output links back to source file and line range.

  1. 1

    Collect XML, Java sources and properties

    Provide all Spring XML files, the jars or modules that contribute XML through classpath imports, Java sources for beans and aspects, and properties files per environment.

  2. 2

    Build the effective bean graph

    PYD ENTERPRISES resolves imports in order, parent definitions, overrides, scopes and autowiring into the object graph the container would create.

  3. 3

    Compute effective behavior per method

    Pointcut expressions are evaluated against every bean method, giving the transaction attributes and advice chain that apply to each one.

  4. 4

    Classify advice as plumbing or business logic

    Aspects that log, time or translate exceptions are classified as plumbing; aspects that change arguments or return values are extracted as business rules.

  5. 5

    Build the property matrix

    Every property reference is resolved per environment with its source file and line, and defaults that are in effect somewhere are flagged.

  6. 6

    Export the wiring inventory and rules

    A wiring inventory, per-method transaction table, extracted rules and fixtures are exported for the Spring Boot team to convert against.

Legacy in, specification out

The source, and what PYD ENTERPRISES extracts from it.

Left: the Spring XML construct as it sits in production. Right: the reviewed artifact your Spring Boot engineers build against. PYD ENTERPRISES produces the spec and the tests; your team writes the service.

LEGACY SOURCE

applicationContext-pricing.xmlXML
1<bean id="pricingService" class="com.example.pricing.PricingServiceImpl">
2 <property name="rateDao" ref="rateDao"/>
3 <property name="maxDiscountPct" value="${pricing.maxDiscount:15}"/>
4</bean>
5
6<tx:advice id="txAdvice" transaction-manager="txManager">
7 <tx:attributes>
8 <tx:method name="get*" read-only="true"/>
9 <tx:method name="*" propagation="REQUIRED"
10 rollback-for="com.example.pricing.PricingException"/>
11 </tx:attributes>
12</tx:advice>
13
14<aop:config>
15 <aop:pointcut id="pricingOps"
16 expression="execution(* com.example.pricing..*Service.*(..))"/>
17 <aop:advisor advice-ref="txAdvice" pointcut-ref="pricingOps"/>
18 <aop:aspect ref="loyaltyAspect">
19 <aop:around pointcut-ref="pricingOps" method="applyLoyaltyDiscount"/>
20 </aop:aspect>
21</aop:config>

EXTRACTED ARTIFACT

pricing.wiring.yamlYAML
1x-pyd-source: applicationContext-pricing.xml:14-38
2beans:
3 pricingService:
4 class: com.example.pricing.PricingServiceImpl
5 injects: [rateDao]
6 properties:
7 maxDiscountPct:
8 key: pricing.maxDiscount
9 default: 15
10 values: { prod: 12, uat: 20, dev: "default (15)" }
11effectiveBehavior:
12 PricingServiceImpl.getQuote:
13 transaction: { propagation: REQUIRED, readOnly: true }
14 advice: [txAdvice, loyaltyAspect.applyLoyaltyDiscount]
15 PricingServiceImpl.applyPrice:
16 transaction:
17 propagation: REQUIRED
18 rollbackFor: [PricingException, RuntimeException, Error]
19 advice: [txAdvice, loyaltyAspect.applyLoyaltyDiscount]
20rulesInAdvice:
21 - id: PRC-LOYAL-04
22 source: LoyaltyAspect.java:31-47
23 rule: "price * (1 - tierDiscount), discount capped at maxDiscountPct"
24 scope: "every *Service method under com.example.pricing"

Architectural best practices

Build the Spring Boot side to the spec, not to the old shape.

  • Convert from the effective bean graph and per-method behavior, not by translating XML elements one at a time.
  • Move business logic out of aspects into explicit service code; keep AOP for cross-cutting plumbing only.
  • Put @Transactional on the methods that need it, with the attributes the inventory shows, instead of relying on naming patterns.
  • Bind configuration with @ConfigurationProperties and validate it at startup, using the property matrix as the test.
  • Resolve every bean override explicitly; do not re-enable allow-bean-definition-overriding to make startup pass.

The conversion is easy. Knowing what to convert is not.

Turning <bean> elements into @Bean methods is routine work, and IDE tooling helps. The risk is everything that happens by pattern: pointcuts that match more than anyone remembers, transaction semantics tied to method names, property references resolved differently per environment, and overrides from jars nobody reads. Those are where Spring Boot migrations break in production.

PYD ENTERPRISES computes the effective configuration and behavior and exports it as an inventory with source links: which beans exist, how each method is transacted and advised, which properties are in effect where, and which aspects carry business rules. Your team writes the Spring Boot configuration; PYD ENTERPRISES does not generate it.

The loyalty aspect in the example

The XML shows an around advice named applyLoyaltyDiscount on every pricing service method. Reading LoyaltyAspect shows it multiplies the returned price by one minus the customer's tier discount, capped at maxDiscountPct. That is a pricing rule, and it applies to any future *Service class in the package. In production the cap is 12, in UAT 20 and in development the XML default of 15, which explains why test results never matched production. The inventory makes all three facts visible, and the business decides where the rule should live.

FAQ

Spring XML to Spring Boot questions

Does PYD ENTERPRISES handle annotation configuration mixed with XML?

Yes. Component scanning, @Autowired, @Transactional and @Aspect annotations are merged with XML definitions into one effective bean graph, applying Spring's precedence rules.

Which Spring versions are supported?

Spring Framework 2.5 through 5.x XML configuration and namespaces (beans, context, aop, tx, util, jee) are supported, which covers most estates still on XML.

Can it read properties from JNDI or a config server?

Values from files are resolved directly. JNDI, system properties and remote config sources are listed as external inputs, and you can supply exported values per environment to complete the matrix.

Get the spec for your Spring XML estate.

Request a codebase scan and review extracted rules, contracts and fixtures for your own Spring XML estate, inside your VPC.