Comments (5)
Hi buddy thanks for your concern but I don't think it makes a lot difference in this case wether you do this:
StringEncryptor encryptor = registry.getBean(beanName, StringEncryptor.class);
or this:
StringEncryptor encryptor = registry.getBean(StringEncryptor.class);
Regardless of the implementation of getBean(name, type)
and getBean(type)
the bean needs to be already instantiated for you to get a hold of it. So at that point the bean needs have been initialized and instantiated already. The post processor pulling the bean guarantees that it's done at the end of wiring the entire application context, so it doesn't mess up with bean initialization order. Basically, if the bean had a dependency on something, it'd had been already instantiated at that point.
Looking the actual implementation of both methods in DefaultListableBeanFactory
it's evident that they both rely on the same method protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
from AbstractBeanFactory
. The actual difference for both is that on getBean(Class<T>)
the implementation is actually looking for candidates names by type first, then the name is used to retrieve the actual bean. The only side effect seems to be for FactoryBean beans, that may get eagerly initialized. But at the point the post processor is invoked the application context is fully wired.
I do think though your recommendation is valuable in the case of having 2 different different StringEncryptor
beans in your application. In that case depending on how you set them up you may end up getting a NoUniqueBeanDefinitionException
in the post processor as Spring wouldn't be able to decide which one to return.
Best,
Uli
from jasypt-spring-boot.
Thank you for a long reply.
I think that the situation is not sufficiently described.
In my case, I try to use mybatis, mybatis-spring for a persistence layer and jasypt-spring-boot for db property encryption. an expected senarios are below.
- jasypt-spring-boot decrypt database connecion info in PropertySources in Spring Envrionment.
- The decrypted db connection infos are used to create DataSource.
- The Datasource can be injected into Mybatis's SessionFactory.
- Mybatis's SessionFactory can be autowired or injected to MapperFactoryBean which is FactoryBean.
- MapperFactoryBean's BeanDefinition's are created in ImportBeanDefinitionRegistrar in Mybatis-Spring, but the BeanDefinition's should be instantiated after 1)~4).
In step 1), jasypt-spring-boot use getBeanByType() to get StringEncryptor. This method result in scanning all types of BeanDefinitions in ApplicationContext to find a matched bean instance. Usual beans are not in a problem for type chekcing, but a FactoryBean which has danamic resultType in getObjectType
Method. MapperFactoryBean in Mybatis-Spring is that case.
The BeanDefinitions are created in MyBatis-Spring's BeanFactoryPostProcessor. The types of proper ObjectTypes are injected by property values. But, Spring's AbstractAutowireCapableBeanFactory.getSingletonFactoryBeanForTypeCheck
does not use that injected property. It just instantiate by default constructor, and then it tries to get getObjectType which return null ( proper type is not yet injected ). If null is returned, spring try to institiate the FactoryBean to check type. so the order of bean creation depedencies are different what I expected.
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(String, RootBeanDefinition)
FactoryBean<?> fb = (mbd.isSingleton() ?
getSingletonFactoryBeanForTypeCheck(beanName, mbd) :
getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
if (fb != null) {
// Try to obtain the FactoryBean's object type from this early stage of the instance.
objectType.value = getTypeForFactoryBean(fb);
// !!!!!!!! objectType.value is null !!!!!!!!!!!!
if (objectType.value != null) {
return objectType.value;
}
}
// !!!!!!!! this cause this issue !!!!!!!!!!!!
// No type found - fall back to full creation of the FactoryBean instance.
return super.getTypeForFactoryBean(beanName, mbd);
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getSingletonFactoryBeanForTypeCheck(String, RootBeanDefinition)
Object instance = null;
try {
// Mark this bean as currently in creation, even if just partially.
beforeSingletonCreation(beanName);
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
instance = resolveBeforeInstantiation(beanName, mbd);
if (instance == null) {
// !!!!!!!!!!!!!! just create without any arguments !!!!!!!!!!!!
bw = createBeanInstance(beanName, mbd, null);
instance = bw.getWrappedInstance();
}
}
finally {
// Finished partial creation of this bean.
afterSingletonCreation(beanName);
}
FactoryBean<?> fb = getFactoryBean(beanName, instance);
if (bw != null) {
this.factoryBeanInstanceCache.put(beanName, bw);
}
( org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getSingletonFactoryBeanForTypeCheck(String, RootBeanDefinition) )
Source References
- [mybatis-spring] MapperScannerRegistrar : http://grepcode.com/file/repo1.maven.org/maven2/org.mybatis/mybatis-spring/1.2.3/org/mybatis/spring/annotation/MapperScannerRegistrar.java#MapperScannerRegistrar.registerBeanDefinitions%28org.springframework.core.type.AnnotationMetadata%2Corg.springframework.beans.factory.support.BeanDefinitionRegistry%29
- [mybatis-spring] MapperFactoryBean : http://grepcode.com/file/repo1.maven.org/maven2/org.mybatis/mybatis-spring/1.2.3/org/mybatis/spring/mapper/MapperFactoryBean.java/
- [spring-bean] AbstractBeanFactory : http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-beans/4.2.0.RELEASE/org/springframework/beans/factory/support/AbstractBeanFactory.java#AbstractBeanFactory.getTypeForFactoryBean%28java.lang.String%2Corg.springframework.beans.factory.support.RootBeanDefinition%29
from jasypt-spring-boot.
Thanks for the explanation. It makes sense. As I said in my previous comment, the only side effect seems to be for FactoryBean beans which unfortunately is your case, so I will fix this.
In terms of the fix, I have a few options to consider:
- By name as you suggested
- ListableFactoryBean provides methods that allow to specify whether to initialize FactoryBean beans when searching for a bean of a specific type. The side effect for Jasypt Spring Boot wold be that the StringEncryptor could not be provided as FactoryBean (Or the FactoryBean would have to be initialized manually, i.e. calling getObject() in a bean definition)
- Allow Specification of the execution order of the EncryptablePropertySourcesPostProcessor. This may not work since you need the properties to be decrypted before the iBatis FactoryBean gets created.
- Delay initialization of StringEncryptor until right before first encrypted property is used. I'm already doing this in the scenario when StringEncryptor is not provided.
from jasypt-spring-boot.
I followed your advice and am retrieving encryptor bean by name as of version 1.6. I just released it to central so it might take some time until it's available. Please review the documentation if you need to specify a custom encryptor as you now have to specify a bean name.
from jasypt-spring-boot.
great work!! thanks
from jasypt-spring-boot.
Related Issues (20)
- I use a Gradle Project. Is this plugin just for maven project? HOT 1
- Spring RabbitMQ credentials can't be encrypted
- Create custom encryptor bean with an error HOT 4
- Password rotation possibility HOT 4
- jasypt-spring-boot 3.0.5 doesn't work with spring boot 2.3.12.RELEASE HOT 1
- Multiple property decryption
- proxy-property-sources=true causes ClassCastException HOT 1
- [BUG] in springboot 2.0.3,the "spring.config.name" properties lose efficacy
- JASYPT fails to bind properties 'spring.datasource.password' while using with ENC() HOT 1
- Is there an unresolvable circular reference HOT 3
- 3.x.x 以后可以自定义加密器吗,配置jasypt.encryptor.bean的方式
- GraalVM native app startup with errors. HOT 1
- Windows and Linux compatibility issues HOT 3
- AES256GCM, Base64 decod of key file failed...
- StackOverflowError with SpringBoot 3.1.5 and jasypt-spring-boot-starter 3.0.5 with ${cors.origins.allowed:#{http://localhost:4200}} HOT 2
- jasypt not decrypting already encrypted property (i.e in application.properties file) in xml based configuration spring boot project HOT 3
- Usage of StandardEncryptableEnvironment with additional active profile(s) and custom prefix and suffix breaks decryption
- String Encryptor custom Bean not found with name 'jasyptStringEncryptor' after upgrading to AWS CLOUD Spring3(implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.4)
- Source code to refer in order to understanding how jasypt able to "intercept" and "massage" the configuration value
- NoSuchAlgorithmException: SHA1PRNG SecureRandom not available HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jasypt-spring-boot.