Why does Mybatis interface not need an implementation class
Yeah, why not? Guess what, maybe the dynamic proxy generates the corresponding class of the interface
When did that happen
That’s what I get when I get the Mapper by class
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Copy the code
Through the above we can get to the code below
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);/ / 1
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession); / / 2
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: "+ e, e); }}Copy the code
- Get the MapperProxyFactory of the corresponding type
- Create a MapperProxy, our UserMapper, on which we can invoke the methods we defined in our interface
How is the proxy generated?
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy); / / 1
}
Copy the code
- Enter newInstance as follows
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
Copy the code
Here we return to the proxy.newProxyInstance code, which is the JDK’s method for creating a Proxy.
Wait, generate Proxy MapperProxyFactory to come
KnownMappers. Get (type) MapperProxyFactory
, mapperInterface
, mapperInterface
Where does MapperProxyFactory come from, SqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); We go all the way to parseConfiguration method, where mapperElement(root.evalNode(“mappers”)); The method is to parse the Mapper file and register the MapperProxyFactory to MapperRegistry. Trace all the way to the following method, in MapperRegistry.
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
knownMappers.put(type, new MapperProxyFactory<>(type)); / / 1
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if(! loadCompleted) { knownMappers.remove(type); }}}Copy the code
- Trace all the way to
knownMappers.put(type, new MapperProxyFactory<>(type));
Method we found, when we created the proxy, was usedget
Method,MapperProxyFactory
That’s where I added it.
conclusion
Today we go from creating proxy objects for Mapper interfaces to how to create objects.
From initializing the configuration file to creating a MapperProxyFactory, to using the JDK dynamic proxy API to create proxy objects based on the type or corresponding MapperProxyFactory when the Mapper is obtained. So we can call the method.
Demonstrate relevant code
Welcome to discuss learning
Use JDK apis for dynamic proxy and source code analysis
Mybatis plugin and dynamic proxy
The interviewer asks why the Mybatis interface does not require an implementation class
How to control the order in which Mybatis enhances logic