如下配置: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对象创建实例对象。
一个普通类包含如下属性信息:
将类上的信息放入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)



