生成RedisTemplate的过程解读

默认创建RedisTemplate的过程

RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
    private boolean enableTransactionSupport = false;
    private boolean exposeConnection = false;
    private boolean initialized = false;
    private boolean enableDefaultSerializer = true;
    @Nullable
    private RedisSerializer<?> defaultSerializer;
    @Nullable
    private ClassLoader classLoader;
    @Nullable
    private RedisSerializer keySerializer = null;
    @Nullable
    private RedisSerializer valueSerializer = null;
    @Nullable
    private RedisSerializer hashKeySerializer = null;
    @Nullable
    private RedisSerializer hashValueSerializer = null;
    private RedisSerializer<String> stringSerializer = RedisSerializer.string();
    @Nullable
    private ScriptExecutor<K> scriptExecutor;
    private final ValueOperations<K, V> valueOps = new DefaultValueOperations(this);
    private final ListOperations<K, V> listOps = new DefaultListOperations(this);
    private final SetOperations<K, V> setOps = new DefaultSetOperations(this);
    private final StreamOperations<K, ?, ?> streamOps = new DefaultStreamOperations(this, ObjectHashMapper.getSharedInstance());
    private final ZSetOperations<K, V> zSetOps = new DefaultZSetOperations(this);
    private final GeoOperations<K, V> geoOps = new DefaultGeoOperations(this);
    private final HyperLogLogOperations<K, V> hllOps = new DefaultHyperLogLogOperations(this);
    private final ClusterOperations<K, V> clusterOps = new DefaultClusterOperations(this);

1.类加载

// Invoked by the VM after loading class with this loader.
    private void checkPackageAccess(Class<?> cls, ProtectionDomain pd) {
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            if (ReflectUtil.isNonPublicProxyClass(cls)) {
                for (Class<?> intf: cls.getInterfaces()) {
                    checkPackageAccess(intf, pd);
                }
                return;
            }

            final String packageName = cls.getPackageName();
            if (!packageName.isEmpty()) {
                AccessController.doPrivileged(new PrivilegedAction<>() {
                    public Void run() {
                        sm.checkPackageAccess(packageName);
                        return null;
                    }
                }, new AccessControlContext(new ProtectionDomain[] {pd}));
            }
        }
    }

2.先执行Object的构造方法,之后执行父类RedisAccessor的构造方法,初始化RedisAccessor的静态,常量成员

public class RedisAccessor implements InitializingBean {
    protected final Log logger = LogFactory.getLog(this.getClass());
    public RedisAccessor() {
    }

3.依次完成RedisTemplate的成员的初始化

// public interface RedisSerializer<T>
    static RedisSerializer<String> string() {
        return StringRedisSerializer.UTF_8;
    }
// class DefaultValueOperations<K, V>
    DefaultValueOperations(RedisTemplate<K, V> template) {
        super(template);
    }
// class DefaultListOperations<K, V>
    DefaultListOperations(RedisTemplate<K, V> template) {
        super(template);
    }
// class DefaultSetOperations
    DefaultSetOperations(RedisTemplate<K, V> template) {
        super(template);
    }
// public class ObjectHashMapper implements HashMapper<Object, byte[], byte[]> 
    public static ObjectHashMapper getSharedInstance() {
        ObjectHashMapper cs = sharedInstance;
        if (cs == null) {
            Class var1 = ObjectHashMapper.class;
            synchronized(ObjectHashMapper.class) {
                cs = sharedInstance;
                if (cs == null) {
                    cs = new ObjectHashMapper();
                    sharedInstance = cs;
                }
            }
        }
        return cs;
    }
// class DefaultStreamOperations<K, HK, HV>
    DefaultStreamOperations(final RedisTemplate<K, ?> template, @Nullable HashMapper<? super K, ? super HK, ? super HV> mapper) {
        super(template);
        ....
    }
// class DefaultZSetOperations<K, V>
    DefaultZSetOperations(RedisTemplate<K, V> template) {
        super(template);
    }
// class DefaultGeoOperations<K, M>
    DefaultGeoOperations(RedisTemplate<K, M> template) {
        super(template);
    }
// class DefaultHyperLogLogOperations<K, V>
    DefaultHyperLogLogOperations(RedisTemplate<K, V> template) {
        super(template);
    }
// class DefaultClusterOperations<K, V>
    DefaultClusterOperations(RedisTemplate<K, V> template) {
        super(template);
        this.template = template;
    }

出现的问题

        System.out.println(redisTemplate.getKeySerializer());	// null
        redisTemplate.opsForValue().set("city","beijing");		// NullPointerException

原因是属性keySerializer默认值为null,执行set方法的时候

// class DefaultValueOperations<K, V> extends AbstractOperations<K, V> 
    public void set(K key, V value) {
        final byte[] rawValue = this.rawValue(value);
        this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
            protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
                connection.set(rawKey, rawValue);
                return null;
            }
        }, true);
    }
// abstract class AbstractOperations<K, V>
    byte[] rawValue(Object value) {
        return this.valueSerializer() == null && value instanceof byte[] ? (byte[])((byte[])value) : this.valueSerializer().serialize(value);
    }
因为 value instanceof byte[]false
所以这里返回了this.valueSerializer().serialize(value)
但是this.valueSerializer()null,所以就报错了

此时,只能使用这种形式

redisTemplate.opsForValue().set("city",new byte[]{12,13});

但是又会报错

java.lang.IllegalArgumentException: template not initialized; call afterPropertiesSet() before using it

	at org.springframework.util.Assert.isTrue(Assert.java:121)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:205)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:189)
	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
	at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:236)
	at guet.ruiji.test.test_redis(test.java:23)

原因是执行set方法的时候,执行execute,属性initialized的默认值为false,所以就报错了

// class DefaultValueOperations<K, V> extends AbstractOperations<K, V>
    public void set(K key, V value) {
        final byte[] rawValue = this.rawValue(value);
        this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
            protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
                connection.set(rawKey, rawValue);
                return null;
            }
        }, true);
    }
// 调用 abstract class AbstractOperations<K, V>
    <T> T execute(RedisCallback<T> callback, boolean exposeConnection) {
        return this.template.execute(callback, exposeConnection);
    }
// 调用 public class RedisTemplate<K, V>
    public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
        return this.execute(action, exposeConnection, false);
    }
// 调用
    public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
        Assert.isTrue(this.initialized, "template not initialized; call afterPropertiesSet() before using it");
		...
    }
// 调用 public abstract class Assert
    public static void isTrue(boolean expression, String message) {
        if (!expression) {
            throw new IllegalArgumentException(message);
        }
    }

@Autowired做了什么

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
    public RedisAutoConfiguration() {
    }
    @Bean
    /**
     * @ConditionalOnMissingBean表示在 Spring容器中如果有一个 Bean的name是 redisTemplate
     * 将不再执行被此注解修饰的方法。
     * @ConditionalOnMissingBean只能在 @Bean注释的方法上使用,不能在@Component注释的类上使用
     */
    @ConditionalOnMissingBean(name = {"redisTemplate"})	
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

创建了RedisTemplate对象之后从这个方法推出之后,会执行doCreateBean方法,这个方法会间接调用很多其他方法。

// public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
			if (instanceWrapper == null) {
			    instanceWrapper = this.createBeanInstance(beanName, mbd, args);
			}
    }
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
            else if (mbd.getFactoryMethodName() != null) {
                return this.instantiateUsingFactoryMethod(beanName, mbd, args);
            }
    }
    protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
        return (new ConstructorResolver(this)).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
    }
// class ConstructorResolver
    public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
        bw.setBeanInstance(this.instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
        return bw;
    }
    private Object instantiate(String beanName, RootBeanDefinition mbd, @Nullable Object factoryBean, Method factoryMethod, Object[] args) {
        try {
            return this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
        }
    }
// public class SimpleInstantiationStrategy
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Object factoryBean, Method factoryMethod, Object... args) {
            Object var9;
            try {
                Object result = factoryMethod.invoke(factoryBean, args);
                if (result == null) {
                    result = new NullBean();
                }
                var9 = result;
            }
    }
// abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        Object exposedObject = bean;
        try {
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } 
    }
    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } 
    }
    protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
          else {
                ((InitializingBean)bean).afterPropertiesSet();
          }
    }
// public class RedisTemplate<K, V> extends RedisAccessor
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        if (this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
        }
		// 可以看到默认采用的是 JdkSerializationRedisSerializer
        if (this.enableDefaultSerializer) {
            if (this.keySerializer == null) {
                this.keySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.valueSerializer == null) {
                this.valueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashKeySerializer == null) {
                this.hashKeySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashValueSerializer == null) {
                this.hashValueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }
        }

        if (this.enableDefaultSerializer && defaultUsed) {
            Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
        }

        if (this.scriptExecutor == null) {
            this.scriptExecutor = new DefaultScriptExecutor(this);
        }

        this.initialized = true;
    }

Spring初始化bean的时候,如果该bean实现了InitializingBean接口,并且指定了init-method,则先调用afterPropertieSet()方法,然后再调用init-method中指定的方法。
1、Spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中通过init-method指定,两种方式可以同时使用。
2、实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率要高一点,但是init-method方式消除了对spring的依赖。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值