Let’s look back at the history of computer development. From the beginning, the first computer covered an area of 170 square meters and weighed 30 tons, to today’s personal notebooks. Things are lighter and more functional. This is the development process of things. A trend in the technology field is also true in the technology field. Enterprise JavaBean (Enterprise JavaBean, EJB) was very successful when it was first created, but over time people began to pursue more convenient, simpler and lightweight technology framework implementations. So Spring came into being, and Spring has been continuously involved in other fields (I won’t go into more details here), and the essence of Spring includes control inversion and dependency injection.
A brief discussion of Inversion of Control (IOC)
Let’s first understand the word control, that is, in the case of “forward” control, in any system with a request function, at least There are two classes working together. Use the new keyword under one entry class to create an object instance of another class. This is like under the idea of object-oriented programming, "I" acts as an entry class. In this entry class, I have to buy a pair of disposable chopsticks every time I eat (new each time I use them). In this relationship, "I" (the caller) has to "take the initiative" to buy disposable chopsticks every time ( Another category), I said to the chopsticks, come over and hold my hand honestly. I control the chopsticks. Well, under this kind of control-forward relationship, it is definitely unrealistic in real life. , and people are lazy, they will always create ideas that are more convenient for their lives. A more precise way is to buy a pair of ordinary chopsticks (not disposable) and put them in a container (called IOC in Spring container), when you need to use it, just say to the container: IOC I want to use chopsticks (send a request to the container), and then the chopsticks will be "injected" into your hand, and in this process, you are no longer the controlling party. , instead evolves into a requester (although it is still a caller), relying on the container to give you resources, and control is located on the container, so this is what people commonly call inversion of control.
Initial introduction to Dependency Injection
Continuing with the above example, under the unity of inversion of control, how did the chopsticks come to my hand (that is, how did we obtain the requested class), this is a dependency The process of injection.
Let’s talk about IOC and DI again
The Hollywood principle in design principles describes, “Don’t look for us, we look for you.” The description of this point on Baidu Encyclopedia is “Don’t call us, we will call you. "Telephone (don't call us, we'll call you)" is a famous Hollywood principle. In Hollywood, after submitting your resume to an acting company, you just go home and wait. Since the performing arts company has complete control over the entire entertainment project, actors can only passively accept the company's tasks and complete their performances when necessary. This is perfectly reflected in IOC. What IOC focuses on is the design concept. It changes from a conventional method of creating objects, that is, new an object, to submitting a "resume" to the IOC container and passively waiting for the IOC container to return resources. for you. Inversion of control refers to "the entertainment company controls the actors", and when it comes to dependence, it means "the actors need the company to work for them". The objects we need need to rely on the container to obtain them. This process is dependency injection. In essence, IOC and DI are manifestations of different dimensions under the same idea.
Code Implementation
Since the process of obtaining resources in inversion of control is called dependency injection, the code implementation here also focuses on dependency injection. There are three methods of dependency injection, namely construction injection, setting injection and interface injection.
1. Interface injection: Define the information to be injected in the interface, and complete the injection through the interface. (Spring does not support this injection method - the reason for not supporting it is - Spring claims that it is non-invasive and "can live without this framework". If interface injection is used, it violates this principle), it will not be done here. Code implementation explanation.
2.Setter injection
We first break away from Spring to implement setter injection
public interface UserDao{ addUser(String username); }
public class UserDaoImpl implements UserDao{ @Override public void addUser(String username) { System.out.println("添加用户:"+username); } }
public class UserMessage{ private UserDao userDao; //使用设值方式赋值 public void setUserDao(UserDaoImpl userDao) { this.userDao = userDao; } @Override public void addUser(String userName, String password) { userDao.addUser(userName, password); } }
We observe carefully, in fact, the approach here is essentially the same as UserDao userDao=new UserDaoImpl(). Here we have to mention polymorphism, that is, the parent class can refer to the subclass method, one of the effects formed here is to reduce the coupling between User Message and UserDao. Thinking about it again, readers may say that is wrong. The inversion of control and dependency injection you mentioned require requesting resources from the container. This container is not extracted above. Let's explain how injection is done in Spring.
<!-- 使用spring管理对象的创建,还有对象的依赖关系 --> <bean id="userManager" class="scau.zzf.service.UserMessage"> <!-- (1)UserMessageImpl使用了userDao,Ioc是自动创建相应的UserDao实现,都是由容器管理--> <!-- (2)在UserMessageImpl中提供构造函数,让spring将UserDao实现注入(DI)过来 --> <!-- (3)让spring管理我们对象的创建和依赖关系,必须将依赖关系配置到spring的核心配置文件中 --> <property name="userDao" ref="UserDao"></property> <!-- 构造注入 --> <!-- <constructor-arg ref="userDao"/> --> </bean> <bean id="UserDao" class="scau.zzf.Dao.UserDao"> </bean>
First we need to assemble the Bean, that is, configure the Bean in the Spring container, and then return the Bean object instance. We can read our xml file through XmlBeanFactory to obtain relevant Bean information.
public class test { public static void main(String[] args) throws Exception { BeanFactory factory=new XmlBeanFactory(new FileSystemResource("src/appllication.xml")); UserMessage userMessage=(UserMessage)factory.getBean("UserMessage"); userMessage.add("德玛西亚"); } }
In actual applications, we do not manually read the information in , of course it is still necessary to understand such a process.
Now let’s briefly explain how to implement injection through annotations.
@Configuration public class UserConfig { @Bean public UserDao getUserDao(){ return new UserDao(); } @Bean public UserMessage getUserMessage(){ return new UserMesssgae(getUserDao); } }
The function of @Configuration is to make the entire class a configuration class. The @Bean annotation will tell Spring that the method under this annotation will return an object, and this object must register the Bean that dimensioned the Spring application context. By default, Spring's beans are singletons, that is, in the above example, no matter how many times we use getUserDao(), the object returned is the same from beginning to end. For further instructions on the configuration of JavaConfig, readers can go to the author's other article "Configuring SSH More Elegantly" for reference.