spring base (II) - IOC and dependency inversion control injection DI

Reprinted article: https: //blog.csdn.net/sinat_21843047/article/details/80297951

IOC

  1. Defined Ioc-Inversion of Control: that is, "Inversion of Control" is not a technical, but a design idea. In Java development, Ioc means that you designed objects to the container control, rather than the traditional direct control over your internal object. Traditional Java SE programming, we directly inside the object on the line through the new object is created, the program is automatically create dependent objects, but there is a special IOC container to create these objects, that is controlled by the ioc container to create objects
    Here Insert Picture Description

IOC benefits

Traditional applications are by our initiative to create dependent objects within a class,Resulting in a high coupling between classesDifficult tests; Once you have IoC container, theCreating and finding dependent objects of control to the container, composite objects are implanted by the container, so between the object and the objects are loosely coupled, which would also facilitate the testing, which will help multiplexing functionMore important is the structure of the program makes the whole system becomes very flexible.

In fact, IoC programming bring the biggest change is not from the code, but ideologically, "master-slave transposition" of change. The application was originally boss, to get what resources are to take the initiative, but in IoC / DI thought, the application becomes passive, and passive waiting IoC container to create and inject the resources it needs.

IOC 与 IN

  1. DI-Dependency Injection, namely "dependency injection": dependency relationships between components at runtime is determined by the vessel, said the image that will be injected by the container dynamic dependencies into a component. Dependency injection is not intended to bring more functionality to software systems, but to enhance component reuse frequencies, and for the system to build a flexible, scalable platform.

DI is the key to understanding: "Who dependence, why rely on, who is who inject, inject something" that we have to analyze in depth:

● Who depends on whom: of course, is application dependent on the IoC container;

● Why rely on: the application needs IoC container to provide external resources required objects;

● Who injection: it is clear that the object is injected into the IoC container application to an object, the application-dependent;

● injected What: an object that is injected into the external resources required (including objects, resources, constant data).

Reference article: https: //blog.csdn.net/a909301740/article/details/78379720

Three ways dependency injection

  1. Constructor Injection
    constructor injection is primarily dependent on the configuration implemented method, the method may be configured to have a reference may be no arguments, (we usually create a class are created by the class constructor and assigned an initial value) the same in reflective spring mechanism, to complete the injection by the constructor (assignment).

Code

  1. Write a related bean class
public class UserService implements IUserService {

	private IUserDao userDao;
	
	public UserService(IUserDao userDao) {
		this.userDao = userDao;
	}
	
	public void loginUser() {
		userDao.loginUser();
	}

}

  1. Relevant configuration (injected into the constructor has a parameter by UserService constructor-arg tag)
<!-- 注册userService -->
<bean id="userService" class="com.lyu.spring.service.impl.UserService">
	<constructor-arg ref="userDaoJdbc"></constructor-arg>
</bean>
<!-- 注册jdbc实现的dao -->
<bean id="userDaoJdbc" class="com.lyu.spring.dao.impl.UserDaoJdbc"></bean>
  1. Test category
@Test
public void testDI() {
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	// 获取bean对象
	UserService userService = ac.getBean(UserService.class, "userService");
	// 模拟用户登录
	userService.loginUser();
}

constructor-arg element argument constructor for the class definition, which is used to define the type of parameter type may be used to define the position of the index parameter, and the value set here is a value above code is through to a Spring assembling a Bean

setter injection

Code

  1. The first is the bean class (be sure to write a setter method)

name attribute value of the class member variable names and parameter names are set regardless of the method, only with the method name corresponding to the set, following such an approach is a combination with a second code is to run a successful

public class UserService implements IUserService {

	private IUserDao userDao1;
	
	public void setUserDao(IUserDao userDao1) {
		this.userDao1 = userDao1;
	}
	
	public void loginUser() {
		userDao1.loginUser();
	}

}

  1. Profiles
    (The following are two ways for writing, spring will name value of the first letter of each word converted to uppercase, and then stitching the "set" in the previous constitute a method name, and then go find the corresponding class of the method , invoked by reflection, realize injection, mainly that he is looking set method, not find the property name)
<!-- 注册userService -->
<bean id="userService" class="com.lyu.spring.service.impl.UserService">
	<!-- 写法一 -->
	<!-- <property name="UserDao" ref="userDaoMyBatis"></property> -->
	<!-- 写法二 -->
	<property name="userDao" ref="userDaoMyBatis"></property>
</bean>

<!-- 注册mybatis实现的dao -->
<bean id="userDaoMyBatis" class="com.lyu.spring.dao.impl.UserDaoMyBatis"></bean>

  1. Precautions: If the injection properties by methods set, will then spring to instantiate objects by default empty constructor parameter, if the configuration of the write method with parameters in a class constructor must take empty write parameters otherwise, spring is no way to instantiate objects, resulting in an error.

Annotation-based injection

  1. First, tell us about a property of the bean autowire of three properties: constructor, byName, byType.
  • constructor: the line is automatically injected through the construction method, the same spring will match the constructor parameter types bean implanting, if one only a constructor parameter to find a constructor, a multi-parameter in the container to a plurality of matching multi-parameter bean constructor, the spring will be preferentially injected into the constructor bean multiple parameters.

  • byName: is injected into the bean id name must match half and after the set method, the first word and the first letter of the name id must be lowercase, which is injected with a different set manually.

  • byType: Find all the set method, in line with the parameter type of bean injection.

There are four main annotation may register bean, each annotation can be any use, but differ on semantics:

@Component: can be used to register all bean
the @Repository: mainly used for registration dao bean layer
@Controller: bean is mainly used for registration control layer
@Service: mainly used for registration service layer bean

@Resource

  1. Definitions: java annotations to default byName way to go to match the same attribute name of the bean id, if not found will look for ways to byType, if byType find more, use @Qualifier annotation (spring annotations) specified bean a specific name.
@Resource
@Qualifier("userDaoMyBatis")
private IUserDao userDao;
public UserService(){
}

@Autowired

  1. Definitions: spring annotation, the default is byType way to match the same type of bean, if only to a match, then injected directly into the bean, no matter what the bean name to be injected is; if multiple matches, it will call DefaultListableBeanFactory of determineAutowireCandidate bean method to determine which specific injection. Method determineAutowireCandidate content as follows:
// candidateBeans 为上一步通过类型匹配到的多个bean,该 Map 中至少有两个元素。
protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
    //  requiredType 为匹配到的接口的类型
   Class<?> requiredType = descriptor.getDependencyType();
   // 1. 先找 Bean 上有@Primary 注解的,有则直接返回
   String primaryCandidate = this.determinePrimaryCandidate(candidateBeans, requiredType);
   if (primaryCandidate != null) {
       return primaryCandidate;
   } else {
       // 2.再找 Bean 上有 @Order,@PriorityOrder 注解的,有则返回
       String priorityCandidate = this.determineHighestPriorityCandidate(candidateBeans, requiredType);
       if (priorityCandidate != null) {
           return priorityCandidate;
       } else {
           Iterator var6 = candidateBeans.entrySet().iterator();

           String candidateBeanName;
           Object beanInstance;
           do {
               if (!var6.hasNext()) {
                   return null;
               }

               // 3. 再找 bean 的名称匹配的
               Entry<String, Object> entry = (Entry)var6.next();
               candidateBeanName = (String)entry.getKey();
               beanInstance = entry.getValue();
           } while(!this.resolvableDependencies.values().contains(beanInstance) && !this.matchesBeanName(candidateBeanName, descriptor.getDependencyName()));

           return candidateBeanName;
       }
   }
}

DetermineAutowireCandidate logic process is:

  • Bean had to go first on @Primary notes, there are the direct return of the bean name.
  • There @ Order, @ PriorityOrder comment on the find Bean, there is the bean name is returned.
  • Finally, the name matches (ByName) to find a way to match the bean.

It can be simply understood as the first to ByType way to matching, if more than one match to another in a way to match ByName, find the corresponding bean went injection, did not find it throws an exception.

Another point to note: If you use @Qualifier annotation, then when multiple bean automatic assembly match when he will not enter determineAutowireCandidate method (pro-test), but directly look the same and @Qualifer specified bean name bean to injection, direct injection found, did not find an exception is thrown.

Published 36 original articles · won praise 11 · views 10000 +

Guess you like

Origin blog.csdn.net/s_xchenzejian/article/details/100887591