When to set proxyBeanMethods to false in Springs #Configuration? - java

When looking at springs autoconfigure source code it seems that every auto-configuration class sets proxyBeanMethods = false.
#Configuration(proxyBeanMethods=false)
public class SomeAutoConfiguration {
...
}
The javadoc gives a detailed explanation for this particular field:
Specify whether {#code #Bean} methods should get proxied in order to enforce
bean lifecycle behavior, e.g. to return shared singleton bean instances even
in case of direct {#code #Bean} method calls in user code. (...)
If this is not needed since each of this particular configuration's {#code #Bean}
methods is self-contained and designed as a plain factory method for container use,
switch this flag to {#code false} in order to avoid CGLIB subclass processing.(...)
After reading this I'm still confused when it is better setting it to false.
Here are my questions:
Can someone give a concrete example when this field should be true and explain why?
Why is this field set to false on the auto-configuration classes?
Update:
Found two issues on github that give some explanation why it is false on most auto-configutation classes:
https://github.com/spring-projects/spring-boot/issues/9068
https://github.com/spring-projects/spring-framework/issues/22461

Something like this:
#Configuration(proxyBeanMethods=true)
public class SomeConfiguration {
#Bean
ServiceA serviceA(){
return new ServiceA(sharedService());
}
#Bean
ServiceB serviceB(){
return new ServiceB(sharedService());
}
#Bean
ServiceC sharedService(){
return new ServiceC();
}
}
Here, the proxyBeanMethods will assure that the 'sharedService' method will be intercepted and its result re-used. If you would follow the normal java logic, when calling serviceA() and serviceB(), there would be two different instances of ServiceC, and when calling sharedService() directly, a third instance would be created. Then proxy interceptor will make sure the actual method is only called once, so only one instance of the shared ServiceC is created, and both ServiceA and ServiceB will get the shared instance.
However proxyBeanMethods=true has a performance cost during startup, especially for libraries with a lot of # Configuration classes, like spring-boot's internal libraries. See e.g. https://github.com/spring-projects/spring-boot/issues/9068#issuecomment-461520814 for the impact on Spring WebFlux.
They couldn't change it to false by default, since that would break backwards compatibility. See links in the original question.
You can use different configuration patterns to avoid this, which is probably what auto-configuration classes do.
One way to do this is auto-wiring the service via method parameters instead of nested method calls. It makes less sence in normal Java, but it works in Spring configurations:
#Configuration(proxyBeanMethods=false)
public class SomeSmarterConfiguration {
#Bean
ServiceC sharedService(){
return new ServiceC();
}
#Bean
ServiceA serviceA(ServiceC sharedService){
return new ServiceA(sharedService);
}
#Bean
ServiceB serviceB(ServiceC sharedService){
return new ServiceB(sharedService);
}
}

Spring introduces proxyBeanMethods in version 5.2. The default value of proxyBeansMethods is true. That implies proxy objects will be generated for classes configured with #Configuration by default. In Springboot version 2 and onwards, all AutoConfiguration classes are configured with #Configuration(proxyBeanMethods = false). This is because the automatic Configuration feature is widely used in SpringBoot. Generating proxy objects will increase the startup time of spring and increase the object memory of the proxy part. The best practice is to annotate configuration classes with #Configuration(proxyBeanMethods = false)

Related

#Transactional annotation at service layer does not rollback, jdbcTemplate [duplicate]

I have recently noticed that Spring successfully intercepts intra class function calls in a #Configuration class but not in a regular bean.
A call like this
#Repository
public class CustomerDAO {
#Transactional(value=TxType.REQUIRED)
public void saveCustomer() {
// some DB stuff here...
saveCustomer2();
}
#Transactional(value=TxType.REQUIRES_NEW)
public void saveCustomer2() {
// more DB stuff here
}
}
fails to start a new transaction because while the code of saveCustomer() executes in the CustomerDAO proxy, the code of saveCustomer2() gets executed in the unwrapped CustomerDAO class, as I can see by looking at 'this' in the debugger, and so Spring has no chance to intercept the call to saveCustomer2.
However, in the following example, when transactionManager() calls createDataSource() it is correctly intercepted and calls createDataSource() of the proxy, not of the unwrapped class, as evidenced by looking at 'this' in the debugger.
#Configuration
public class PersistenceJPAConfig {
#Bean
public DriverManagerDataSource createDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//dataSource.set ... DB stuff here
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager( ){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(createDataSource());
return transactionManager;
}
}
So my question is, why can Spring correctly intercept the intra class function calls in the second example, but not in the first. Is it using different types of dynamic proxies?
Edit:
From the answers here and other sources I now understand the following:
#Transactional is implemented using Spring AOP, where the proxy pattern is carried out by wrapping/composition of the user class. The AOP proxy is generic enough so that many Aspects can be chained together, and may be a CGLib proxy or a Java Dynamic Proxy.
In the #Configuration class, Spring also uses CGLib to create an enhanced class which inherits from the user #Configuration class, and overrides the user's #Bean functions with ones that do some extra work before calling the user's/super function such as check if this is the first invocation of the function or not. Is this class a proxy? It depends on the definition. You may say that it is a proxy which uses inheritance from the real object instead of wrapping it using composition.
To sum up, from the answers given here I understand these are two entirely different mechanisms. Why these design choices were made is another, open question.
Is it using different types of dynamic proxies?
Almost exactly
Let's figure out what's the difference between #Configuration classes and AOP proxies answering the following questions:
Why self-invoked #Transactional method has no transactional semantics even though Spring is capable of intercepting self-invoked methods?
How #Configuration and AOP are related?
Why self-invoked #Transactional method has no transactional semantics?
Short answer:
This is how AOP made.
Long answer:
Declarative transaction management relies on AOP (for the majority of Spring applications on Spring AOP)
The Spring Framework’s declarative transaction management is made possible with Spring aspect-oriented programming (AOP)
It is proxy-based (§5.8.1. Understanding AOP Proxies)
Spring AOP is proxy-based.
From the same paragraph SimplePojo.java:
public class SimplePojo implements Pojo {
public void foo() {
// this next method invocation is a direct call on the 'this' reference
this.bar();
}
public void bar() {
// some logic...
}
}
And a snippet proxying it:
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
The key thing to understand here is that the client code inside the main(..) method of the Main class has a reference to the proxy.
This means that method calls on that object reference are calls on the proxy.
As a result, the proxy can delegate to all of the interceptors (advice) that are relevant to that particular method call.
However, once the call has finally reached the target object (the SimplePojo, reference in this case), any method calls that it may make on itself, such as this.bar() or this.foo(), are going to be invoked against the this reference, and not the proxy.
This has important implications. It means that self-invocation is not going to result in the advice associated with a method invocation getting a chance to execute.
(Key parts are emphasized.)
You may think that aop works as follows:
Imagine we have a Foo class which we want to proxy:
Foo.java:
public class Foo {
public int getInt() {
return 42;
}
}
There is nothing special. Just getInt method returning 42
An interceptor:
Interceptor.java:
public interface Interceptor {
Object invoke(InterceptingFoo interceptingFoo);
}
LogInterceptor.java (for demonstration):
public class LogInterceptor implements Interceptor {
#Override
public Object invoke(InterceptingFoo interceptingFoo) {
System.out.println("log. before");
try {
return interceptingFoo.getInt();
} finally {
System.out.println("log. after");
}
}
}
InvokeTargetInterceptor.java:
public class InvokeTargetInterceptor implements Interceptor {
#Override
public Object invoke(InterceptingFoo interceptingFoo) {
try {
System.out.println("Invoking target");
Object targetRetVal = interceptingFoo.method.invoke(interceptingFoo.target);
System.out.println("Target returned " + targetRetVal);
return targetRetVal;
} catch (Throwable t) {
throw new RuntimeException(t);
} finally {
System.out.println("Invoked target");
}
}
}
Finally InterceptingFoo.java:
public class InterceptingFoo extends Foo {
public Foo target;
public List<Interceptor> interceptors = new ArrayList<>();
public int index = 0;
public Method method;
#Override
public int getInt() {
try {
Interceptor interceptor = interceptors.get(index++);
return (Integer) interceptor.invoke(this);
} finally {
index--;
}
}
}
Wiring everything together:
public static void main(String[] args) throws Throwable {
Foo target = new Foo();
InterceptingFoo interceptingFoo = new InterceptingFoo();
interceptingFoo.method = Foo.class.getDeclaredMethod("getInt");
interceptingFoo.target = target;
interceptingFoo.interceptors.add(new LogInterceptor());
interceptingFoo.interceptors.add(new InvokeTargetInterceptor());
interceptingFoo.getInt();
interceptingFoo.getInt();
}
Will print:
log. before
Invoking target
Target returned 42
Invoked target
log. after
log. before
Invoking target
Target returned 42
Invoked target
log. after
Now let's take a look at ReflectiveMethodInvocation.
Here is a part of its proceed method:
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
++this.currentInterceptorIndex should look familiar now
Here is the target
And there are interceptors
the method
the index
You may try introducing several aspects into your application and see the stack growing at the proceed method when advised method is invoked
Finally everything ends up at MethodProxy.
From its invoke method javadoc:
Invoke the original method, on a different object of the same type.
And as I mentioned previously documentation:
once the call has finally reached the target object any method calls that it may make on itself are going to be invoked against the this reference, and not the proxy
I hope now, more or less, it's clear why.
How #Configuration and AOP are related?
The answer is they are not related.
So Spring here is free to do whatever it wants. Here it is not tied to the proxy AOP semantics.
It enhances such classes using ConfigurationClassEnhancer.
Take a look at:
CALLBACKS
BeanMethodInterceptor
BeanFactoryAwareMethodInterceptor
Returning to the question
If Spring can successfully intercept intra class function calls in a #Configuration class, why does it not support it in a regular bean?
I hope from technical point of view it is clear why.
Now my thoughts from non-technical side:
I think it is not done because Spring AOP is here long enough...
Since Spring Framework 5 the Spring WebFlux framework has been introduced.
Currently Spring Team is working hard towards enhancing reactive programming model
See some notable recent blog posts:
Reactive Transactions with Spring
Spring Data R2DBC 1.0 M2 and Spring Boot starter released
Going Reactive with Spring, Coroutines and Kotlin Flow
More and more features towards less-proxying approach of building Spring applications are introduced. (see this commit for example)
So I think that even though it might be possible to do what you've described it is far from Spring Team's #1 priority for now
Because AOP proxies and #Configuration class serve a different purpose, and are implemented in a significantly different ways (even though both involve using proxies).
Basically, AOP uses composition while #Configuration uses inheritance.
AOP proxies
The way these work is basically that they create proxies that do the relevant advice logic before/after delegating the call to the original (proxied) object. The container registers this proxy instead of the proxied object itself, so all dependencies are set to this proxy and all calls from one bean to another go through this proxy. However, the proxied object itself has no pointer to the proxy (it doesn't know it's proxied, only the proxy has a pointer to the target object). So any calls within that object to other methods don't go through the proxy.
(I'm only adding this here for contrast with #Configuration, since you seem to have correct understanding of this part.)
#Configuration
Now while the objects that you usually apply the AOP proxy to are a standard part of your application, the #Configuration class is different - for one, you probably never intend to create any instances of that class directly yourself. This class truly is just a way to write configuration of the bean container, has no meaning outside Spring and you know that it will be used by Spring in a special way and that it has some special semantics outside of just plain Java code - e.g. that #Bean-annotated methods actually define Spring beans.
Because of this, Spring can do much more radical things to this class without worrying that it will break something in your code (remember, you know that you only provide this class for Spring, and you aren't going to ever create or use its instance directly).
What it actually does is it creates a proxy that's subclass of the #Configuration class. This way, it can intercept invocation of every (non-final non-private) method of the #Configuration class, even within the same object (because the methods are effectively all overriden by the proxy, and Java has all the methods virtual). The proxy does exactly this to redirect any method calls that it recognizes to be (semantically) references to Spring beans to the actual bean instances instead of invoking the superclass method.
read a bit spring source code. I try to answer it.
the point is how spring deal with the #Configurationand #bean.
in the ConfigurationClassPostProcessor which is a BeanFactoryPostProcessor, it will enhance all ConfigurationClasses and creat a Enhancer as a subClass.
this Enhancer register two CALLBACKS(BeanMethodInterceptor,BeanFactoryAwareMethodInterceptor).
you call PersistenceJPAConfig method will go through the CALLBACKS. in BeanMethodInterceptor,it will get bean from spring container.
it may be not clearly. you can see the source code in ConfigurationClassEnhancer.java BeanMethodInterceptor.ConfigurationClassPostProcessor.java enhanceConfigurationClasses
You can't call #Transactional method in same class
It's a limitation of Spring AOP (dynamic objects and cglib).
If you configure Spring to use AspectJ to handle the transactions, your code will work.
The simple and probably best alternative is to refactor your code. For example one class that handles users and one that process each user. Then default transaction handling with Spring AOP will work.
Also #Transactional should be on Service layer and not on #Repository
transactions belong on the Service layer. It's the one that knows about units of work and use cases. It's the right answer if you have several DAOs injected into a Service that need to work together in a single transaction.
So you need to rethink your transaction approach, so your methods can be reuse in a flow including several other DAO operations that are roll-able
Spring uses proxying for method invocation and when you use this... it bypasses that proxy. For #Bean annotations Spring uses reflection to find them.

How to limit a Spring #Configuration class to instantiating only alternate services?

I have a project which is expanding quickly and now has over a hundred components. For unit testing, I have a #Configuration class to substitute stubbed classes, such as a database service with limited functionality:
#Configuration
public class SpringDevTestConfiguration {
#Bean
#Profile("unittest")
public DatabaseService databaseService() {
// this one is needed for the test
return new TestDatabaseServiceImpl();
}
#Bean
#Profile("unittest")
public RobotControlService robotControlService() {
// Why should I do this on every service?
return new RobotControlServiceImpl();
}
... etc.
The vast majority of components don't need test alternatives, so we want the default one that exists and is picked up at runtime. But whenever a new component is added to the system, we have to add it to all of the #Configuration classes, or we get the "NoSuchBeanDefinitionException: No qualifying bean of type..." exception. That's a lot of boilerplate code to return Impl classes, and prevents us from making implementation classes package-protected (because the configuration class needs to be able to instantiate them).
I have tried adding #ComponentScan to the class, but that results in BeanDefinitionOverrideException. If I allow bean overrides with:
spring.main.allow-bean-definition-overriding=true
... then I get NoUniqueBeanDefinitionException because of the multiple database service implementations.
I'm sure I must be missing something. How can I have short, simple #Configuration class that only instantiates the test implementations I need for the test, then allows the other services to be discovered automatically without explicitly creating them?

Why Spring's #Transactional works without proxy?

I got interested in how Spring's #Transactional works internally, but everywhere I read about it there's a concept of proxy. Proxies are supposed to be autowired in place of real bean and "decorate" base method with additional transaction handling methods.
The theory is quite clear to me and makes perfect sense so I tried to check how it works in action.
I created a Spring Boot application with a basic controller and service layers and marked one method with #Transactional annotation. Service looks like this:
public class TestService implements ITestService {
#PersistenceContext
EntityManager entityManager;
#Transactional
public void doSomething() {
System.out.println("Service...");
entityManager.persist(new TestEntity("XYZ"));
}}
Controller calls the service:
public class TestController {
#Autowired
ITestService testService;
#PostMapping("/doSomething")
public ResponseEntity addHero() {
testService.doSomething();
System.out.println(Proxy.isProxyClass(testService.getClass()));
System.out.println(testService);
return new ResponseEntity(HttpStatus.OK);
}}
The whole thing works, new entity is persisted to the DB but the whole point of my concern is the output:
Service...
false
com.example.demo.TestService#7fb48179
It seems that the service class was injected explicitly instead of proxy class. Not only "isProxy" returns false, but also the class output ("com.example.demo.TestService#7fb48179") suggests its not a proxy.
Could you please help me out with that? Why wasn't the proxy injected, and how does it even work without proxy? Is there any way I can "force" it to be proxied, and if so - why the proxy is not injected by default by Spring ?
There's not much to be added, this is a really simple app. Application properties are nothing fancy either :
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=superSecretPassword
spring.datasource.url=jdbc:mysql://localhost:3306/heroes?serverTimezone=UTC
spring.jpa.hibernate.ddl-auto=create-drop
Thank you in advance!
Your understanding is correct, but your test is flawed:
When the spring docs say "proxy", they are referring to the pattern, not a particular implementation. Spring supports various strategies for creating proxy objects. One of these is the java.lang.reflect.Proxy you tested for, but by default spring uses a more advanced technique that generates a new class definition at runtime that subclasses the actual implementation class of the service (and overrides all methods to apply transaction advice). You can see this in action by checking testService.getClass(), which will refer to that generated class, or by halting execution in a debugger, and inspecting the fields of targetService.
The reason that toString() refers to the original object is that the proxy implements toString() by delegating to its target object, which uses its class name to build the String.

Programmatically mimick #Bean method to register several instances as beans

(spring boot 1.5, java 8)
Suppose there is a Foundation, some Wall types, and Ceilings. They depend on each other, just like their physical counterparts.
This configuration class has a Foundation injected and creates Wall beans, so that Ceilings can have Walls injected. Don't mind the bad practices, I'm just trying to keep the code as short as possible without changing the essential mechanisms.
#Configuration
class Config {
#Autowired
Foundation foundation;
#Bean
// assume there is a lot of repetitive logic here
WoodenWall wood() { return new WoodenWall(foundation); }
#Bean
BrickWall brick() { return new BrickWall(foundation); }
}
And a ceiling:
#Component
class KitchenCeiling {
#Autowired
WoodWall wall;
}
I'm going to be making a lot more Wall types and want them all registered as beans. Instead of having to define a #Bean method for each and every one of them, I want to instantiate them all in a loop and register them manually in a single go. Think of an AllTypesOfWallsBeanFactory if you wish.
#Configuration
class Config implements ??? {
#Autowired
Foundation foundation;
#Override
void addBeans(??? beanRegistry) {
for (Class beanClass : wallClasses) {
// instantiate BrickWall, WoodWall, etc
registry.add(beanClass.getSimpleName(), beanClass, wallInstance);
}
}
}
The problem is, I can't find the right interface to implement or the right SpringBeanRegistryPostProcessorFactoryImplementationThingamajig to go to. I've tried the answers given on all the other SO posts I could find but none do the right thing.
One issue here is that I need the context to already be initializing beans since I need a Foundation, but I also want to add some more beans to the context so that Ceilings yet to be initialized can inject my freshly made Walls.
#Bean methods do exactly that: they can take dependencies that are already initialized and return new beans to be used elsewhere at the same time. I just need the programmatic equivalent to this exact mechanism.
I know dependency resolution is harder in this situation (since there isn't any reflective information for spring to figure out the total following order), but it's gotta be possible to tell spring to
initialize what it has dependencies for
process the newly created beans
goto 1
BeanDefinition doesn't fit the bill because it doesn't take any instances, and to use the factoryMethod setting I would need to make a factory class for each Wall. Back to square one.
Most of the BeanDefinitionRegistryPostProcessor et al interfaces are called too late, don't inject the beans I give them into dependent beans (there was 1 that took instances but didn't do anything with them), or demand a default constructor (i.e. no dependencies). They also tend to give you objects that only take BeanDefinition.
In another project where there was a similar need, what ended up being used was a factory method with still a #Bean method for each instance it needed to produce. I'm starting to think it isn't really possible and what was done in this project is as good as it'll get.
You can try using #PostConstructwith ConfigurableApplicationContext
#Configuration
class Config {
#Autowired
Foundation foundation;
#Autowired
ConfigurableApplicationContext ctx;
#PostConstruct
void addBeans() {
for (Class beanClass : wallClasses) {
ctx.getBeanFactory().registerSingleton(beanClass.getSimpleName(), beanClass, wallInstance);
}
}
}
I'm going to conclude that it just isn't possible to do this reliably. The best one can do is making a factory method and a #Bean method calling the factory for each bean instance that needs to be registered. It doesn't seem possible to cut the #Bean methods out of the picture.

Create proxy for a interface, which could inject by #Autowired, proxy invokes different implement by key parameter

I want to define a annotation like #PlatformRelated, once it is marked in a interface, there will be a proxy bean at spring context, and this proxy bean should be #Priority.I want this proxy could invoke different implement according to key parameter #KeyPrameter.And I still wanna use spring features like #Async,#Trasaction,etc... at my Implement1 and Implement2.
#PlatformRelated
interface MyInterface {
method(#KeyPrameter String parameter);
}
#Component
class Implement1 implements MyInterface {
method(String parameter){
//do something 111
}
}
#Component
class Implement2 implements MyInterface {
method(String parameter){
//do something 222
}
}
#Service
class BusinessService{
#Autowired
private MyInterface myInterface;
public void doSomething() {
myInterface.method("key1");
//Implement1 work
myInterface.method("key2");
//Implement2 work
}
}
Do you guys have some good idea to complete it?
I must admit I haven't totally understood the meaning #Priority, however, I can say that if you want to implement this feature in spring, you should probably take a look at Bean Post Processors.
BeanPostProcessors are essentially a hook to Bean Creation process in spring intended for altering bean behavior.
Among other things, they allow wrapping the underlying bean into the proxy (CGLIB/java.lang.Proxy if you're working with interfaces, or even using programmatically Spring AOP), these proxies can provide a hook to the method execution that can read your annotations (like mentioned #KeyParameter) and execute a code in a way similar to Aspect's code that you already make use of.
Not all bean post processor wrap the bean into the proxy. For example, if you want to implement a BPP that uses "#Autowire", you will return the same bean, just "inject" (read, put by reflection) its dependencies. On the other hand, if you want to implement with BPP #Transactional behavior, then yes, you should wrap the bean into a proxy that would take care of transaction management capabilities before and after the method execution.
It's totally ok to have a spring bean that gets "altered" by many post processors, some of them would wrap it into a proxy other will just modify-and-return the same bean, If there are many BPP-s that wrap the bean into proxy we'll get "proxy inside proxy inside proxy" (you get the idea). Each layer of proxy will handle one specific behavior.
As an example, I suggest you take a look at existing Spring postprocessors, or, for instance, a source code of the following library: Spring Boot metering integration library
This library contains some implementations of post processors that allow metrics infrastructure integration by defining annotations on methods of Spring Beans.

Categories