默认创建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的依赖。