Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I limit Spring component scan to only files in my war?

Tags:

java

spring

jboss

I am using Spring's component scan to find beans in my app.

<context:component-scan base-package="com.myapp"/>

However the performance when the app is deployed on our staging server (JBoss 5 with a lot of apps deployed) is much slower than in development (also JBoss 5 but few apps). The component scan takes a long time. I suspect this is due to a much larger classpath?

Is there an easy way to get Spring to only look for beans in my war file? i.e. WEB-INF/classes and WEB-INF/lib? Or is there another solution?

like image 874
David Tinker Avatar asked Jun 17 '11 06:06

David Tinker


People also ask

How do I specify component scans in Spring boot?

With Spring, we use the @ComponentScan annotation along with the @Configuration annotation to specify the packages that we want to be scanned. @ComponentScan without arguments tells Spring to scan the current package and all of its sub-packages.

How do I disable component scan in Spring boot?

To disable the default filter, set the useDefaultFilters element of the @ComponentScan annotation to false.

What is @configuration @EnableAutoConfiguration and ComponentScan?

@EnableAutoConfiguration : enable Spring Boot's auto-configuration mechanism. @ComponentScan : enable @Component scan on the package where the application is located (see the best practices) @Configuration : allow to register extra beans in the context or import additional configuration classes.

What is classpath scanning in Spring?

A Classpath scanning basically means, detecting the classes that need to be managed by the Spring under a specified package. You need to make use of the spring @ComponentScan annotation with the @Configuration for classpath scanning.


4 Answers

Two tips;

  • try to be as specific with the base-package(s) as you can: you can provide several packages in the base-package attribute, separated by commas.
  • use filters; check docs here. - you can specify annotations which are to be scanned (e.g. if you only use @Component) and you also can specify a regex which the classname will have to match.
like image 198
abalogh Avatar answered Nov 03 '22 01:11

abalogh


I don't know if you have a solution in place but a colleague and I have a potential solution.

In full disclosure we work for Red Hat on the Snowdrop project, which provides support for Spring apps on JBoss.

The potential solution is to use a component-scan within snowdrop's jboss namespace - https://github.com/snowdrop/snowdrop/tree/CustomBeanScanner

Using that you could add the custom component scanner so instead of <context:component-scan base-package="foo.bar"/>, you would use: <jboss:component-scan base-package="foo.bar"/>.

We know it works but we don't know if anyone would want to change their application to make use of the feature. Is the intentional coupling worth the speed increase?

The code is out there on the branch listed above for anyone to try/use.

thanks, Joshua

like image 32
Joshua Wilson Avatar answered Nov 03 '22 02:11

Joshua Wilson


You should set the classpath scanning settings to your package (eg. "com.foo"). However - the number of classes in your classpath should not be much different in staging versus development. It will be your WAR plus server-wide classes, which should be roughly the same. Specifically you will not have classes from other WARs in your classpath.

I suspect the server is overloaded. You should get some statistics from that machine: ie, what is the CPU utilization? Is there a lot of disk I/O? Is is paging/swapping excessively? Also check the memory utilization of the JVM - maybe it is spending a lot of time doing garbage collection.

like image 28
sourcedelica Avatar answered Nov 03 '22 00:11

sourcedelica


What if you specify

<context:component-scan base-package="com.myapp" resource-pattern="/WEB-INF/classes/**/*.class"/>

or some alternative of this approach?

like image 27
Jiří Vypědřík Avatar answered Nov 03 '22 02:11

Jiří Vypědřík