catalogue
1. Analysis and Implementation
1. Analysis and Implementation
Let's write a piece of code in our original way
- First write a UserDao interface
public interface UserDao { public void getUser(); }
- Then write Dao's implementation class
public class UserDaoImpl implements UserDao { @Override public void getUser() { System.out.println("Get user data"); } }
- Then write the UserService interface
public interface UserService { public void getUser(); }
- Finally, write the implementation class of Service
public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoImpl(); @Override public void getUser() { userDao.getUser(); } }
- test
@Test public void test(){ UserService service = new UserServiceImpl(); service.getUser(); }
This is our original way. At first, everyone wrote it like this, right? Let's revise it now
Add an implementation class of Userdao
public class UserDaoMySqlImpl implements UserDao { @Override public void getUser() { System.out.println("MySql Get user data"); } }
Next, if we want to use MySql, we need to modify the corresponding implementation in the service implementation class
public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoMySqlImpl(); @Override public void getUser() { userDao.getUser(); } }
In the assumption, we add another Userdao implementation class
public class UserDaoOracleImpl implements UserDao { @Override public void getUser() { System.out.println("Oracle Get user data"); } }
If we want to use Oracle, we need to modify the corresponding implementation in the service implementation class. Assuming that our demand is very large, this method is not applicable at all, Every time you change, you need to modify a lot of code. The coupling of this design is too high, which will affect the whole body. If you want to change, our ioc will appear.
-
Instead of implementing it, we can set aside an interface where we need it. Using set, we can modify it in the code. Use DI injection (set method)
public class UserServiceImpl implements UserService { private UserDao userDao; // Using set public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); } }
Now go to our test class and test;
@Test public void test(){ UserServiceImpl service = new UserServiceImpl(); service.setUserDao( new UserDaoMySqlImpl() ); service.getUser(); //So now we want to use Oracle to implement it service.setUserDao( new UserDaoOracleImpl() ); service.getUser(); }
Summary; Have you found that the coupling between our programs has been reduced and the control of the program has been reversed. Now the program only provides one interface and does not control others. The specific implementation is operated by ourselves. This is the so-called control inversion (IoC), one of the two characteristics of spring. IoC mode can be regarded as the sublimation of factory mode----------------------------- The IoC container is regarded as a big factory, but the objects to be generated in this big factory are defined in the XML file. Using Java's "reflection" programming, the corresponding objects are generated according to the class definition given in XML. From the implementation point of view, for the objects previously written in the factory mode, the IoC mode is changed to the configuration XML file, which isolates the factory from the objects to be generated, greatly improving the flexibility and maintainability.
The most basic Java technology in IoC is "reflection" programming. Generally speaking, reflection is to generate objects according to the given class name (string). This programming method allows the application to dynamically decide which object to generate at run time. Reflection is widely used. For example, Hibernate and Spring use "reflection" as the most basic technical means.
In the past, reflective programming was 10 times slower than normal object generation, which may be why at that time Reflection technology There is no reason for widespread application. However, after SUN's improvement and optimization, the speed of object generation in reflection mode is not much different from that in normal object generation mode (but there is still more than double the gap).
2, IOC essence
Inversion of control (IoC) is a design idea. DI (dependency injection) is a method to realize IoC. Some people think that DI is just another way of saying IoC. In programs without IoC, we use object-oriented programming. The creation of objects and the dependencies between objects are completely hard coded. In programs, the creation of objects is controlled by the program itself. After the control is reversed, the creation of objects is transferred to a third party. Personally, I think the so-called control reversal is the reversal of the way to obtain dependent objects.
During initialization, the Spring container reads the configuration file first, creates and organizes objects according to the configuration file or metadata, and stores them in the container. When the program is used, it takes out the required objects from the Ioc container.
When configuring a Bean in XML, the definition information of the Bean is separated from the implementation, and the annotation method can integrate the two. The definition information of the Bean is directly defined in the implementation class in the form of annotation, so as to achieve the purpose of zero configuration.
Inversion of control is a way to produce or obtain specific objects through description (XML or annotation) and through a third party. In Spring, the IoC container implements control inversion, and its implementation method is dependency injection (DI).