PropertySource named ‘xxx‘ does not exist、MutablePropertySources源码解析

🌴Caused by: java.lang.IllegalArgumentException: PropertySource named ‘configurationProperties’ does not exist、MutablePropertySources源码解析

🍉一、遭遇配置找不到

Caused by: java.lang.IllegalArgumentException: PropertySource named ‘configurationProperties’ does not exist

泻水置平地,各自东西南北流。
人生亦有命,安能行叹复坐愁?
酌酒以自宽,举杯断绝歌路难。
心非木石岂无感,吞声踯躅不敢言。-------鲍照《拟行路难·其四》

一首小诗开场,愁呀愁。好端端的 Springboot 项目说罢工就罢工,启动不了,直接开摆。

上日志:

Skip ProjectInfoInitializer.
2024-03-28 19:30:29.023  INFO 73744 --- [           main] c.t.zj.dossier.DossierApplication        : Starting DossierApplication on xiezhongcaideMacBook-Pro.local with PID 73744 (started by xiezhongcai in /Users/xiezhongcai/code/thunisoft/浙江一张网/dossier-application)
2024-03-28 19:30:29.024  INFO 73744 --- [           main] c.t.zj.dossier.DossierApplication        : The following profiles are active: ext
2024-03-28 19:30:29.048  INFO 73744 --- [           main] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2024-03-28 19:30:30.003  INFO 73744 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2024-03-28 19:30:30.005  INFO 73744 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2024-03-28 19:30:30.022  INFO 73744 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 9ms. Found 0 repository interfaces.
2024-03-28 19:30:30.232  INFO 73744 --- [           main] e.p.ArteryEncryptPropertiesPostProcessor : 开始处理PropertySource
2024-03-28 19:30:41.189  INFO 73744 --- [           main] ptablePropertiesBeanFactoryPostProcessor : Post-processing PropertySource instances
2024-03-28 19:30:41.232  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource configurationProperties [org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource$$EnhancerBySpringCGLIB$$28713cba] to EncryptablePropertySourceWrapper
2024-03-28 19:30:41.232  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource servletConfigInitParams [org.springframework.core.env.PropertySource$StubPropertySource$$EnhancerBySpringCGLIB$$6454f49a] to EncryptablePropertySourceWrapper
2024-03-28 19:30:41.232  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource servletContextInitParams [org.springframework.core.env.PropertySource$StubPropertySource$$EnhancerBySpringCGLIB$$6454f49a] to EncryptablePropertySourceWrapper
2024-03-28 19:30:41.233  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource systemProperties [org.springframework.core.env.PropertiesPropertySource$$EnhancerBySpringCGLIB$$a9823f25] to EncryptableMapPropertySourceWrapper
2024-03-28 19:30:41.233  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource systemEnvironment [org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource$$EnhancerBySpringCGLIB$$2cfae3c4] to EncryptableSystemEnvironmentPropertySourceWrapper
2024-03-28 19:30:41.233  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource random [org.springframework.boot.env.RandomValuePropertySource$$EnhancerBySpringCGLIB$$941a0e61] to EncryptablePropertySourceWrapper
2024-03-28 19:30:41.233  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource applicationConfig: [classpath:/application-ext.yml] [com.thunisoft.artery.spring.property.encrypt.decorator.ArteryEncryptMapPropertySourceDecorator] to EncryptableMapPropertySourceWrapper
2024-03-28 19:30:41.233  INFO 73744 --- [           main] c.u.j.EncryptablePropertySourceConverter : Converting PropertySource applicationConfig: [classpath:/application.yml] [com.thunisoft.artery.spring.property.encrypt.decorator.ArteryEncryptMapPropertySourceDecorator] to EncryptableMapPropertySourceWrapper
2024-03-28 19:30:43.628 ERROR 73744 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalArgumentException: PropertySource named 'configurationProperties' does not exist
	at org.springframework.core.env.MutablePropertySources.assertPresentAndGetIndex(MutablePropertySources.java:206)
	at org.springframework.core.env.MutablePropertySources.replace(MutablePropertySources.java:156)
	at com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter.lambda$convertPropertySources$2(EncryptablePropertySourceConverter.java:32)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter.convertPropertySources(EncryptablePropertySourceConverter.java:32)
	at com.ulisesbocchio.jasyptspringboot.configuration.EnableEncryptablePropertiesBeanFactoryPostProcessor.postProcessBeanFactory(EnableEncryptablePropertiesBeanFactoryPostProcessor.java:52)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:286)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:174)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
	at com.thunisoft.zj.dossier.DossierApplication.main(DossierApplication.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.taobao.pandora.boot.loader.LaunchRunner.run(LaunchRunner.java:38)
	at java.lang.Thread.run(Thread.java:750)

Stopping available components
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.taobao.pandora.boot.loader.LaunchRunner.run(LaunchRunner.java:38)
	at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.IllegalArgumentException: PropertySource named 'configurationProperties' does not exist
	at org.springframework.core.env.MutablePropertySources.assertPresentAndGetIndex(MutablePropertySources.java:206)
	at org.springframework.core.env.MutablePropertySources.replace(MutablePropertySources.java:156)
	at com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter.lambda$convertPropertySources$2(EncryptablePropertySourceConverter.java:32)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter.convertPropertySources(EncryptablePropertySourceConverter.java:32)
	at com.ulisesbocchio.jasyptspringboot.configuration.EnableEncryptablePropertiesBeanFactoryPostProcessor.postProcessBeanFactory(EnableEncryptablePropertiesBeanFactoryPostProcessor.java:52)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:286)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:174)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
	at com.thunisoft.zj.dossier.DossierApplication.main(DossierApplication.java:38)
	... 6 more
Exception in thread "main" java.lang.RuntimeException: An exception occurred while running. null
	at com.taobao.pandora.boot.loader.IsolatedThreadGroup.rethrowUncaughtException(IsolatedThreadGroup.java:28)
	at com.taobao.pandora.boot.loader.ReLaunchMainLauncher.reLaunch(ReLaunchMainLauncher.java:108)
	at com.taobao.pandora.boot.loader.ReLaunchMainLauncher.launch(ReLaunchMainLauncher.java:40)
	at com.taobao.pandora.boot.PandoraBootstrap.run(PandoraBootstrap.java:48)
	at com.thunisoft.zj.dossier.DossierApplication.main(DossierApplication.java:37)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.taobao.pandora.boot.loader.LaunchRunner.run(LaunchRunner.java:38)
	at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.IllegalArgumentException: PropertySource named 'configurationProperties' does not exist
	at org.springframework.core.env.MutablePropertySources.assertPresentAndGetIndex(MutablePropertySources.java:206)
	at org.springframework.core.env.MutablePropertySources.replace(MutablePropertySources.java:156)
	at com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter.lambda$convertPropertySources$2(EncryptablePropertySourceConverter.java:32)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter.convertPropertySources(EncryptablePropertySourceConverter.java:32)
	at com.ulisesbocchio.jasyptspringboot.configuration.EnableEncryptablePropertiesBeanFactoryPostProcessor.postProcessBeanFactory(EnableEncryptablePropertiesBeanFactoryPostProcessor.java:52)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:286)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:174)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
	at com.thunisoft.zj.dossier.DossierApplication.main(DossierApplication.java:38)
	... 6 more
Disconnected from the target VM, address: '127.0.0.1:51029', transport: 'socket'

Process finished with exit code 1

这日志都打印出来了,这不有手就行吗。

java.lang.IllegalArgumentException: PropertySource named 'configurationProperties' does not exist

快快快,把这个配置文件给我,我不就能启动了吗?

在这里插入图片描述

很遗憾,这个配置文件不是我们自己的,是 Springboot 的,怎么回事呢?

🌵二、MutablePropertySources

org.springframework.core.env.MutablePropertySources这个类报错了,从日志上这里是外层的报错,我来看看怎么个事

/**
 * The default implementation of the {@link PropertySources} interface.
 * Allows manipulation of contained property sources and provides a constructor
 * for copying an existing {@code PropertySources} instance.
 *
 * <p>Where <em>precedence</em> is mentioned in methods such as {@link #addFirst}
 * and {@link #addLast}, this is with regard to the order in which property sources
 * will be searched when resolving a given property with a {@link PropertyResolver}.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see PropertySourcesPropertyResolver
 */
public class MutablePropertySources implements PropertySources {
private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<>();

这个 List 维护了所有的配置文件,都会放到这里来

	/**
	 * Replace the property source with the given name with the given property source object.
	 * @param name the name of the property source to find and replace
	 * @param propertySource the replacement property source
	 * @throws IllegalArgumentException if no property source with the given name is present
	 * @see #contains
	 */
	public void replace(String name, PropertySource<?> propertySource) {
		int index = assertPresentAndGetIndex(name);
		this.propertySourceList.set(index, propertySource);
	}

这方法是根据名称去 List 里面找同名的配置文件,然后替换放进去,等会报错的代码就是这一行int index = assertPresentAndGetIndex(name);

	/**
	 * Assert that the named property source is present and return its index.
	 * @param name {@linkplain PropertySource#getName() name of the property source} to find
	 * @throws IllegalArgumentException if the named property source is not present
	 */
	private int assertPresentAndGetIndex(String name) {
		int index = this.propertySourceList.indexOf(PropertySource.named(name));
		if (index == -1) {
			throw new IllegalArgumentException("PropertySource named '" + name + "' does not exist");
		}
		return index;
	}

🥝三、断点调试

分析调试

在这里插入图片描述

项目启动之初,就看到加载了 8 个配置文件,并且 configurationProperties 是加载到 List 里面了。

此时经过了公司内部封装的一个配置文件加密类
在这里插入图片描述

获取到MutablePropertySources的 List,遍历它进行加密之后再放回 List

在这里插入图片描述

放进来的时候,注意看 name=null,这里就坏事了,加密后放进来 name 为空了。后面要是再调用int index = this.propertySourceList.indexOf(PropertySource.named(name));通过name 去获取它、替换它就会返回空报错了。

好巧不巧,同事又引入了一个依赖想对配置文件进行加密

  <!--ENC加解密 -->
    <dependency>
      <groupId>com.github.ulisesbocchio</groupId>
      <artifactId>jasypt-spring-boot-starter</artifactId>
      <version>2.1.2</version>
    </dependency>

在这里插入图片描述

跟踪到这里,我心里已经有了答案,两次加密:一次是公司封装的,一次是引入的jasypt进行加密

在这里插入图片描述

但是这个锅不能甩给 jasypt,它加密后放进来name 也是有的

在这里插入图片描述

都是加密,为啥公司这个加密后,name 就没了呢?

ArteryEncryptPropertiesPostProcessor走的代理去生成的 PropertySource 对象

private <T> PropertySource<T> proxyPropertySource(PropertySource<T> propertySource, ArteryEncryptPropertyResolver resolver) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTargetClass(propertySource.getClass());
        proxyFactory.setProxyTargetClass(true);
        proxyFactory.addInterface(ArteryEncryptPropertySource.class);
        proxyFactory.setTarget(propertySource);
        proxyFactory.addAdvice(new ArteryEncryptPropertySourceMethodInterceptor(propertySource, resolver));
        return (PropertySource)proxyFactory.getProxy();
    }

jasypt的EncryptablePropertySourceConverter去判断了一下,是否要走代理去成

private static <T> PropertySource<T> convertPropertySource(InterceptionMode interceptionMode, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, PropertySource<T> propertySource) {
        return interceptionMode == InterceptionMode.PROXY
                ? proxyPropertySource(propertySource, propertyResolver, propertyFilter) : instantiatePropertySource(propertySource, propertyResolver, propertyFilter);
    }

这里interceptionMode是WRAPPER,并没有走代理,instantiatePropertySource(propertySource, propertyResolver, propertyFilter)直接包装返回了,如果走代理也是一样的处理方法,name 也会为空

源码

最后附上两个加密的类

ArteryEncryptPropertiesPostProcessor.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.thunisoft.artery.spring.property.encrypt.processor;

import com.thunisoft.artery.spring.property.encrypt.ArteryEncryptPropertySource;
import com.thunisoft.artery.spring.property.encrypt.aop.ArteryEncryptPropertySourceMethodInterceptor;
import com.thunisoft.artery.spring.property.encrypt.decorator.ArteryEncryptEnumerablePropertySourceDecorator;
import com.thunisoft.artery.spring.property.encrypt.decorator.ArteryEncryptMapPropertySourceDecorator;
import com.thunisoft.artery.spring.property.encrypt.decorator.ArteryEncryptPropertySourceDecorator;
import com.thunisoft.artery.spring.property.encrypt.resolver.ArteryEncryptPropertyResolver;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;
import org.springframework.core.env.CommandLinePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

public class ArteryEncryptPropertiesPostProcessor implements BeanFactoryPostProcessor, Ordered {
    private static Logger logger = LoggerFactory.getLogger(ArteryEncryptPropertiesPostProcessor.class);
    private ConfigurableEnvironment environment;

    public ArteryEncryptPropertiesPostProcessor(ConfigurableEnvironment environment) {
        this.environment = environment;
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        logger.info("开始处理PropertySource");
        MutablePropertySources propSources = this.environment.getPropertySources();
        ((List)StreamSupport.stream(propSources.spliterator(), false).filter((ps) -> {
            return !(ps instanceof ArteryEncryptPropertySource);
        }).map((ps) -> {
            return this.makeEncrypt(ps, beanFactory);
        }).collect(Collectors.toList())).forEach((ps) -> {
            propSources.replace(ps.getName(), ps);
        });
    }

    private <T> PropertySource<T> makeEncrypt(PropertySource<T> propertySource, BeanFactory bf) {
        ArteryEncryptPropertyResolver propertyResolver = (ArteryEncryptPropertyResolver)bf.getBean(ArteryEncryptPropertyResolver.class);

        try {
            if (!CommandLinePropertySource.class.isAssignableFrom(propertySource.getClass()) && !Modifier.isFinal(propertySource.getClass().getModifiers())) {
                logger.debug("尝试代理propertySource:{}", propertySource.getName());
                return this.proxyPropertySource(propertySource, propertyResolver);
            } else {
                logger.debug("尝试包装propertySource:{}", propertySource.getName());
                return this.decoratorPropertySource(propertySource, propertyResolver);
            }
        } catch (Exception var5) {
            logger.warn("生成代理出错, 忽略此类:{}", propertySource.getClass().getName(), var5);
            return propertySource;
        }
    }

    private <T> PropertySource<T> proxyPropertySource(PropertySource<T> propertySource, ArteryEncryptPropertyResolver resolver) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTargetClass(propertySource.getClass());
        proxyFactory.setProxyTargetClass(true);
        proxyFactory.addInterface(ArteryEncryptPropertySource.class);
        proxyFactory.setTarget(propertySource);
        proxyFactory.addAdvice(new ArteryEncryptPropertySourceMethodInterceptor(propertySource, resolver));
        return (PropertySource)proxyFactory.getProxy();
    }

    private <T> PropertySource<T> decoratorPropertySource(PropertySource<T> propertySource, ArteryEncryptPropertyResolver resolver) {
        if (propertySource instanceof MapPropertySource) {
            return new ArteryEncryptMapPropertySourceDecorator((MapPropertySource)propertySource, resolver);
        } else {
            return (PropertySource)(propertySource instanceof EnumerablePropertySource ? new ArteryEncryptEnumerablePropertySourceDecorator((EnumerablePropertySource)propertySource, resolver) : new ArteryEncryptPropertySourceDecorator(propertySource, resolver));
        }
    }

    public int getOrder() {
        return Integer.MAX_VALUE;
    }
}

EncryptablePropertySourceConverter.java

package com.ulisesbocchio.jasyptspringboot;

import com.ulisesbocchio.jasyptspringboot.aop.EncryptableMutablePropertySourcesInterceptor;
import com.ulisesbocchio.jasyptspringboot.aop.EncryptablePropertySourceMethodInterceptor;
import com.ulisesbocchio.jasyptspringboot.wrapper.EncryptableEnumerablePropertySourceWrapper;
import com.ulisesbocchio.jasyptspringboot.wrapper.EncryptableMapPropertySourceWrapper;
import com.ulisesbocchio.jasyptspringboot.wrapper.EncryptablePropertySourceWrapper;
import com.ulisesbocchio.jasyptspringboot.wrapper.EncryptableSystemEnvironmentPropertySourceWrapper;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.env.*;

import java.lang.reflect.Modifier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.stream.Collectors.toList;

/**
 * @author Ulises Bocchio
 */
@Slf4j
public class EncryptablePropertySourceConverter {

    public static void convertPropertySources(InterceptionMode interceptionMode, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, MutablePropertySources propSources) {
        StreamSupport.stream(propSources.spliterator(), false)
                .filter(ps -> !(ps instanceof EncryptablePropertySource))
                .map(ps -> makeEncryptable(interceptionMode, propertyResolver, propertyFilter, ps))
                .collect(toList())
                .forEach(ps -> propSources.replace(ps.getName(), ps));
    }

    @SuppressWarnings("unchecked")
    public static <T> PropertySource<T> makeEncryptable(InterceptionMode interceptionMode, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, PropertySource<T> propertySource) {
        if (propertySource instanceof EncryptablePropertySource) {
            return propertySource;
        }
        PropertySource<T> encryptablePropertySource = convertPropertySource(interceptionMode, propertyResolver, propertyFilter, propertySource);
        log.info("Converting PropertySource {} [{}] to {}", propertySource.getName(), propertySource.getClass().getName(),
                AopUtils.isAopProxy(encryptablePropertySource) ? "AOP Proxy" : encryptablePropertySource.getClass().getSimpleName());
        return encryptablePropertySource;
    }

    private static <T> PropertySource<T> convertPropertySource(InterceptionMode interceptionMode, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, PropertySource<T> propertySource) {
        return interceptionMode == InterceptionMode.PROXY
                ? proxyPropertySource(propertySource, propertyResolver, propertyFilter) : instantiatePropertySource(propertySource, propertyResolver, propertyFilter);
    }

    public static MutablePropertySources proxyPropertySources(InterceptionMode interceptionMode, EncryptablePropertyResolver propertyResolver, EncryptablePropertyFilter propertyFilter, MutablePropertySources propertySources) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(MutablePropertySources.class);
        proxyFactory.setProxyTargetClass(true);
        proxyFactory.addInterface(PropertySources.class);
        proxyFactory.setTarget(propertySources);
        proxyFactory.addAdvice(new EncryptableMutablePropertySourcesInterceptor(interceptionMode, propertyResolver, propertyFilter));
        return (MutablePropertySources) proxyFactory.getProxy();
    }

    @SuppressWarnings("unchecked")
    public static <T> PropertySource<T> proxyPropertySource(PropertySource<T> propertySource, EncryptablePropertyResolver resolver, EncryptablePropertyFilter propertyFilter) {
        //Silly Chris Beams for making CommandLinePropertySource getProperty and containsProperty methods final. Those methods
        //can't be proxied with CGLib because of it. So fallback to wrapper for Command Line Arguments only.
        if (CommandLinePropertySource.class.isAssignableFrom(propertySource.getClass())
            // Other PropertySource classes like org.springframework.boot.env.OriginTrackedMapPropertySource
            // are final classes as well
            || Modifier.isFinal(propertySource.getClass().getModifiers())) {
            return instantiatePropertySource(propertySource, resolver, propertyFilter);
        }            
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTargetClass(propertySource.getClass());
        proxyFactory.setProxyTargetClass(true);
        proxyFactory.addInterface(EncryptablePropertySource.class);
        proxyFactory.setTarget(propertySource);
        proxyFactory.addAdvice(new EncryptablePropertySourceMethodInterceptor<>(propertySource, resolver, propertyFilter));
        return (PropertySource<T>) proxyFactory.getProxy();
    }

    @SuppressWarnings("unchecked")
    public static <T> PropertySource<T> instantiatePropertySource(PropertySource<T> propertySource, EncryptablePropertyResolver resolver, EncryptablePropertyFilter propertyFilter) {
        PropertySource<T> encryptablePropertySource;
        if (needsProxyAnyway(propertySource)) {
            encryptablePropertySource = proxyPropertySource(propertySource, resolver, propertyFilter);
        } else if (propertySource instanceof  SystemEnvironmentPropertySource) {
            encryptablePropertySource = (PropertySource<T>) new EncryptableSystemEnvironmentPropertySourceWrapper((SystemEnvironmentPropertySource) propertySource, resolver, propertyFilter);
        } else if (propertySource instanceof MapPropertySource) {
            encryptablePropertySource = (PropertySource<T>) new EncryptableMapPropertySourceWrapper((MapPropertySource) propertySource, resolver, propertyFilter);
        } else if (propertySource instanceof EnumerablePropertySource) {
            encryptablePropertySource = new EncryptableEnumerablePropertySourceWrapper<>((EnumerablePropertySource) propertySource, resolver, propertyFilter);
        } else {
            encryptablePropertySource = new EncryptablePropertySourceWrapper<>(propertySource, resolver, propertyFilter);
        }
        return encryptablePropertySource;
    }

    @SuppressWarnings("unchecked")
    private static boolean needsProxyAnyway(PropertySource<?> ps) {
        return needsProxyAnyway((Class<? extends PropertySource<?>>) ps.getClass());
    }

    private static boolean needsProxyAnyway(Class<? extends PropertySource<?>> psClass) {
        return needsProxyAnyway(psClass.getName());
    }

    /**
     *  Some Spring Boot code actually casts property sources to this specific type so must be proxied.
     */
    private static boolean needsProxyAnyway(String className) {
        return Stream.of(
                "org.springframework.boot.context.config.ConfigFileApplicationListener$ConfigurationPropertySources",
                "org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource"
                ).anyMatch(className::equals);
    }
}

🍅四、解决方法

很遗憾,人生就是一个不断妥协的过程,代码也是。公司封装的加密无法取缔,那么只有寻找它山之石。

最终我把jasypt 删掉了,确实好使了。告诉同事后,他心怀愧疚,连夜换了一个依赖

<dependency>
  <groupId>org.jasypt</groupId>
  <artifactId>jasypt</artifactId>
  <version>1.9.3</version>
</dependency>

看了下代码,这个加密方法,没有了对MutablePropertySources下List 进行操作,留个悬念,这两个依赖有什么区别呢?关注我,我将继续为大家解惑

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值