百度网盘--spring书籍
1. spring创建Bean
如下配置:Spring是将接口UserMapper交给MapperFactoryBean, 实现里面的方法,产生一个代理对象,这样,代码中就可以使用@Autowired进行注入使用;
//依赖xml, 单个mapper
<bean id = "userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"
<property name="mappInterface" ref="org.mybatis.spring.sample.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
探究Spring是如何产生动态代理的?
package com.feng.mapper;
import com.feng.dto.UserDTO;
import org.apache.ibatis.annotations.Insert;
public interface UserMapper {
@Insert("select * from tab_user")
public void selectUser(UserDTO userDTO);
}
Spring 创建的动态代理类UserMapper是如何注入Spring容器中的?
@Service
public class UserService {
/**
* userMapper:Object
* 动态代理
*/
@Autowired
private UserMapper userMapper;
public void save(Map<String, Object> map){
UserDTO userDTO = new UserDTO();
userDTO.setId("111");
userDTO.setUsername("zhangsan");
userMapper.selectUser(userDTO);
}
}
而我们自己代理产生的对象不在容器中,没办法注入
Class[] clazz = new Class[]{ UserMapper.class };
UserMapper userMapper = (UserMapper)Proxy.newProxyInstance(
this.getClass().getClassLoader(),
clazz,
new UserMapperHandler());
解决问题?
如何把一个代理对象放入Spring容器中?
Spring是如何放容器的?
Spring实例化bean 读取类上的注解信息,比如@Compent
spring先解析xml文件或者注解配置,读取所有要加载类信息。根据类信息创建对应的BeanDefinition对象,再根据Beandefination对象创建实例对象。
一个普通类包含如下属性信息:
- name
- scope
- 构造方法
- 注入模型(byName or byType)
- lazy
- static
将类上的信息放入BD中(BeanDefinition),如果有多个类就创建多个BD ,然后将DB放入BeanDefinitionMap中;
BeanDefinition是SpringBean的描述对象,主要封装了如下信息:
此时,如果程序员提供了一个类实现接口: BeanFactotyPostProcessor
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
spring 将先处理实现类中的逻辑(可以拿到Map,进而修改了beanClass)
然后Spring调用方法 preInstantiateSingletons, 根据BD中类的信息, 将bean给new出来;
package org.springframework.beans.factory.config;
import java.util.Iterator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.lang.Nullable;
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
void registerResolvableDependency(Class<?> var1, @Nullable Object var2);
boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
Iterator<String> getBeanNamesIterator();
//
void preInstantiateSingletons() throws BeansException;
}
如果想要把代理对象放入容器中,就新生成一个BeanDefinition, 然后将BD放入Spring容器中,但是BeanFactotyPostProcessor 只提供了update方法,而没有提供add方法
如何放入?
Spring提供类一个接口:ImportBeanDefinitionRegistrar,可以注册BeanDefinition
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
BeanDefinitionBuilder bdBuilder = BeanDefinition.genericBeanDefinition(UserFactoryBean.class);
AbstractBeanDefinition beanDefinition = bdBuilder.getBeanDefinition();
beanDefinition.getConstructorArgumentValues()
.addGenericArgumentValue("com.feng.mapper.UserMapper");
registry.registerBeanDefinition("UserFactoryBean", beanDefinition);
}
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
FactoryBean 是一个bean,而且是一个特殊的bean,它实现了接口(依赖)
@Import(ImportBeanDefinitionRegistrar.class)
小结:Spring实例化一个Bean中,重要的三个接口:
- BeanFactotyPostProcessor
- ImportBeanDefinitionRegistrar
- FactoryBean