05.Detailed explanation of Spring’s Bean configuration

Introduction

The development of Spring applications based on xml mainly focuses on the configuration of beans. The common configuration of beans will be explained in detail below.

1. Overview of common configurations

Xml configuration method Function description
<bean id="" class="" /> Bean id and fully qualified name configuration
<bean name="" /> Set the alias of the Bean through name, and you can also directly obtain the Bean instance through the alias.
<bean scope="" /> The scope of Bean, the value of singleton and prototyp when BeanFactory is used as a container
<bean lazy-init="" /> Bean instantiation timing and whether to delay loading. BeanFactory is invalid as a container
<bean init-method="" /> Load the ApplicationContext of the xml configuration under the disk path
<bean destroy-method="" /> The method before the Bean instance is destroyed, method specifies the method name
<bean autowire="byType"/> Set the automatic injection mode. Commonly used ones are by type byType and by name byName.
<bean factory-bean="" factory-method=""/> Specify which method of which factory bean completes the creation of the bean

2. Simple configuration summary of Bean

For the configuration steps of bean.xml and other parts of the code, please refer to 02.Spring's BeanFactory.
For the configuration steps of applicationContext.xml and other parts of the code, please refer to 03.Spring's ApplicationContext.

2.1 Basic configuration of Bean

For example: Configuring UserDaoImpl is managed by the Spring container

<bean id="userDao" class="com.test.dao.impl.UserDaoImpl"/>

At this time, the beanName of the bean stored in the Spring container (singleObjects singleton pool) is userDao, and the value is the UserDaoImpl object. You can obtain the Bean instance based on the beanName.

applicationContext.getBean("userDao");

If id is not configured, Spring will use the fully qualified name of the current Bean instance as beanName.

applicationContext.getBean("com.test.dao.impl.UserDaoImpl");

Insert image description here

2.2 Bean alias configuration

Multiple aliases can be specified for the current Bean, and the Bean object can also be obtained based on the aliases.

<bean id="userDao" name="aaa,bbb" class="com.test.dao.impl.UserDaoImpl"/>

At this time, multiple names can obtain UserDaoImpl instance objects.

applicationContext.getBean("userDao");
applicationContext.getBean("aaa");
applicationContext.getBean("bbb");

2.3 Bean scope configuration

By default, pure Spring environment beans have two scopes: Singleton and Prototype
singleton: singleton, default value . When the Spring container is created, the bean will be instantiated and stored in the singleton pool inside the container. middle,Every time you getBean, you get the same Bean instance from the singleton pool.;
Prototype: Prototype , the Bean instance will not be created when the Spring container is initialized, and the Bean will be instantiated only when getBean is called.Each time getBean creates a new Bean instance

scope is set to singleton

When the scope is set to singleton, the printing result of obtaining the object twice is the same.

<bean id="userDao" class="com.test.dao.impl.UserDaoImpl" scope="singleton"/>

Insert image description here

Through breakpoint debugging, you can observe that there is a userDao instance in the singleton pool.

Insert image description here

scope is set to prototype

When the scope is set to prototype, the printing results of the two objects are different.

<bean id="userDao" class="com.test.dao.impl.UserDaoImpl" scope="prototype"/>

Insert image description here

Through breakpoint debugging, observation can be found that there is no userDao instance in the singleton pool, but the userDao information has been stored in the beanDefinitionMap.

Insert image description here

Insert image description here

2.4 Lazy loading of Beans

When lazy-init is set to true, it is lazy loading. That is, when the Spring container is created, the Bean instance will not be created immediately. When it is used, the Bean instance will be created and stored in the singleton pool, and the Bean will be used later. You can get it directly from the singleton pool. Essentially, the Bean is still a singleton.

<bean id="userDao" class="com.test.dao.impl.UserDaoImpl" lazy-init="true"/>

You can see that debug goes to getBean, and userDao is only in the singleton pool.

Insert image description here

Insert image description here

2.5 Bean initialization and destruction method configuration

After a Bean is instantiated, it can execute the specified initialization method to complete some initialization operations. Before the Bean is destroyed, it can also execute the specified destruction method to complete some operations.

<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" init-method="init" 
destroy-method="destroy"/>
public class UserDaoImpl implements UserDao {
    
    

    public UserDaoImpl() {
    
     System.out.println("UserDaoImpl创建了..."); }
   
    @Override
    public void init(){
    
    
        System.out.println("init初始化方法执行...");
    }
    @Override
    public void destroy() {
    
    
        System.out.println("destroy方法执行....");
    }
}

init initialization method execution:

Insert image description here

destroy initialization method execution:

Insert image description here

In addition, we can also complete some Bean initialization (destruction) operations by implementing the InitializingBean (DisposableBean) interface.

public class UserDaoImpl implements UserDao, InitializingBean {
    
    
   public UserDaoImpl() {
    
    System.out.println("UserDaoImpl创建了...");}
   public void init(){
    
    System.out.println("初始化方法...");}
   public void destroy(){
    
    System.out.println("销毁方法...");}
   //执行时机早于init-method配置的方法
   public void afterPropertiesSet() throws Exception {
    
    
   System.out.println("InitializingBean..."); 
   }
}
public class MyBean implements DisposableBean {
    
    

    public void destroy() {
    
    
        // 在这里执行资源清理和善后工作
        // 执行时机早于destroy-method配置的方法
        System.out.println("MyBean destroyed");
    }

}

3. Bean instantiation configuration

Spring's instantiation methods are mainly as follows:

Construction method instantiation: The bottom layer instantiates the Bean through the construction method
Factory method instantiation: The bottom layer instantiates the Bean by calling a custom factory method

3.1 Instantiation of construction method

Bean instantiation by construction method is divided into parameterless construction method instantiation and parameterized construction method instantiation.

Almost all configurations in Spring <bean>are configured in this way without parameters, so I won’t go into details here. The following explains the parameterized constructor method to instantiate Bean.

//有参构造方法
public UserDaoImpl(String name){
    
    
}

Parameterized construction requires the injection of parameters when instantiating a bean. The construction parameters are provided through <constructor-arg>tags and embedded inside the tags, as follows:<bean>

<bean id="userDao" class="com.test.dao.impl.UserDaoImpl">
    <constructor-arg name="name" value="haohao"/>
</bean>

3.2 Factory method instantiation

Factory method instantiation of beans is divided into the following three types:
static factory method instantiation of Bean
instance factory method of instantiation of Bean
implementation of FactoryBean specification delayed instantiation of Bean

static factory method

Static factory method to instantiate beans, in fact, it is to define a factory class and provide a static method for producing Bean instances. Then configure the factory class and its static method to Spring.

<bean id="userDao" class="com.test.factory.MyBeanFactory1" factory-method="userDao">
     <constructor-arg name="name" value="test"/>
     <constructor-arg name="age" value="13"/>
</bean>
public class MyBeanFactory1 {
    
    

    public static UserDao userDao(String name,int age){
    
    
        //Bean创建之前可以进行一些其他业务逻辑操作
        return new UserDaoImpl();
    }

}

<constructor-arg>Tags are not only used to pass parameters for constructors, as long as the parameters passed to instantiate the object can be <constructor-arg>completed through tags, for example, the parameters passed above to instantiate the Bean through the static factory method must also be passed <constructor-arg>through

To test the code, you can obtain userDao directly through ApplicationContext. For breakpoint debugging, the UserDaoImpl instance object will exist in the singleton pool.

Insert image description here

instance factory method

instance factory method, that is, the non-static factory method generates Bean instances. Compared with the static factory method, this method requires a factory object first, and then uses the factory object to call the non-static method. Therefore, when configuring, you must first configure the worker Bean and then configure the target. Bean

<!-- 配置实例工厂Bean -->
<bean id="userDaoFactoryBean2" class="com.test.factory.MyBeanFactory2"/>

<!-- 配置实例工厂Bean的哪个方法作为工厂方法 -->
<bean id="userDao" factory-bean="userDaoFactoryBean2" factory-method="userDao">
     <constructor-arg name="username" value="test"/>
</bean>

public class MyBeanFactory2 {
    
    

    public UserDao userDao(String username){
    
    
        //Bean创建之前可以进行一些其他业务逻辑操作
        return new UserDaoImpl();
    }

}

For breakpoint debugging, UserDaoImpl instance objects will also exist in the singleton pool (static and non-static are not delayed loading).
There are both factory bean instances and target bean instances in the singleton pool , and the instantiation of the beans is completed when the Spring container is created.

Insert image description here

Implement FactoryBean specification (lazy instantiation)

Whether it is a static factory method or a non-static factory method, they are all custom factory methods. Spring provides the interface specification of FactoryBean.FactoryBean interface definitionas follows:

public interface FactoryBean<T> {
    
    

      String OBJECT_TYPE_ATTRIBUTE = “factoryBeanObjectType”;
      
      T getObject() throws Exception; //获得实例对象方法
      
      Class<?> getObjectType(); //获得实例对象类型方法
      
      default boolean isSingleton() {
    
    
          return true;
      }
}

Define factory implementation FactoryBean

public class MyBeanFactory3 implements FactoryBean<UserDao> {
    
    

    @Override
    public UserDao getObject() throws Exception {
    
    
        System.out.println("getObject被调用...");
        return new UserDaoImpl();
    }

    @Override
    public Class<?> getObjectType() {
    
    
        return UserDao.class;
    }
}

Configure FactoryBean and let Spring manage it

<bean id="userDao3" class="com.test.factory.MyBeanFactory3"/>

Through breakpoint observation, it was found that when the Spring container was created, MyBeanFactory3 was instantiated and stored in the singleton object pool, but the getObject() method has not yet been executed, and UserDaoImpl has not been instantiated. It is called when UserDaoImpl is used for the first time . getObject(), the Bean instance generated by this factory method will not be stored in the singleton object pool, but will be stored in the factoryBeanObjectCache cache pool, and every time userDao3 is used later, the same userDao3 instance will be returned from the cache pool .

Insert image description here

Insert image description here

4. Bean dependency injection configuration

4.1 Injection method

There are two ways of dependency injection of beans:

Injection method Configuration method
Injection through Bean's set method <property name="userDao" ref="userDao"/> <property name="userDao" value="haohao"/>
Injection through the method of constructing the Bean <constructor-arg name="name" ref="userDao"/> <constructor-arg name="name" value="haohao"/>

Among them, ref is the abbreviation of reference, which is translated as: involving, reference meaning, used to refer to the id of other Beans. value is used to inject ordinary property values.

4.2 Data types

There are three types of data types for dependency injection:

type describe
Common data types For example: String, int, boolean, etc., specified through the value attribute
Reference data type For example: UserDaoImpl, DataSource, etc., specified through the ref attribute.
Collection data type For example: List, Map, Properties, etc.

Inject List collection – ordinary data

public void setStrList(List<String> strList){
    
    
    strList.forEach(str->{
    
    
        System.out.println(str);
    });
 }
<property name="strList">
   <list>
      <value>haohao</value>
      <value>miaomiao</value>
   </list>
</property>

Inject List collection – reference data

public void setObjList(List<UserDao> objList){
    
    
     objList.forEach(obj->{
    
    
        System.out.println(obj);
     });
}
<property name="objList">
   <list>
      <bean class="com.test.dao.impl.UserDaoImpl"></bean>
      <bean class="com.test.dao.impl.UserDaoImpl"></bean>
      <bean class="com.test.dao.impl.UserDaoImpl"></bean>
   </list>
</property>

You can also directly reference beans that exist in the container

<!--配置UserDao-->
<bean id="userDao" class="com.test.dao.impl.UserDaoImpl"/>
<bean id="userDao2" class="com.test.dao.impl.UserDaoImpl"/>
<bean id="userDao3" class="com.test.dao.impl.UserDaoImpl"/>

<!--配置UserService-->
<bean id="userService" class="com.test.service.impl.UserServiceImpl">
        <property name="objList">
               <list>
                   <ref bean="userDao"></ref>
                   <ref bean="userDao2"></ref>
                   <ref bean="userDao3"></ref>
               </list>
        </property>
</bean>

Inject Set collection

//注入泛型为字符串的Set集合
public void setValueSet(Set<String> valueSet){
    
    
   valueSet.forEach(str->{
    
    
        System.out.println(str);
   });
}
//注入泛型为对象的Set集合
public void setObjSet(Set<UserDao> objSet){
    
    
   objSet.forEach(obj->{
    
    
        System.out.println(obj);
   });
}
<!-- 注入泛型为字符串的Set集合 -->
<property name="valueSet">
    <set>
       <value>111111</value>
       <value>222222</value>
    </set>
</property>
<!-- 注入泛型为对象的Set集合 -->
<property name="objSet">
    <set>
       <ref bean="userDao"></ref>
       <ref bean="userDao2"></ref>
       <ref bean="userDao3"></ref>
    </set>
</property>

Inject Map<K,V> collection

//注入值为字符串的Map集合
public void setValueMap(Map<String,String> valueMap){
    
    
     valueMap.forEach((k,v)->{
    
    
        System.out.println(k+"=="+v);
     });
}
//注入值为对象的Map集合
public void setObjMap(Map<String,UserDao> objMap){
    
    
     objMap.forEach((k,v)->{
    
    
        System.out.println(k+"=="+v);
     });
}
<!--注入值为字符串的Map集合-->
<property name="valueMap">
   <map>
     <entry key="aaa" value="AAA" />
     <entry key="bbb" value="BBB" />
     <entry key="ccc" value="CCC" />
   </map>
</property>
<!--注入值为对象的Map集合-->
<property name="objMap">
   <map>
     <entry key="ud" value-ref="userDao"/>
     <entry key="ud2" value-ref="userDao2"/>
     <entry key="ud3" value-ref="userDao3"/>
   </map>
</property>

Inject Properties key-value pairs

//注入Properties
public void setProperties(Properties properties){
    
    
     properties.forEach((k,v)->{
    
    
        System.out.println(k+"=="+v);
     });
}
<property name="properties">
   <props>
      <prop key="xxx">XXX</prop>
      <prop key="yyy">YYY</prop>
   </props>
</property>

4.3 Automatic assembly

If the injected attribute type is a Bean reference, you can <bean>use the autowire attribute in the tag to configure the automatic injection method. There are two attribute values:
byName : automatic assembly through the attribute name, that is, to match setXxx and id="xxx" ( name="xxx") are consistent;
byType : Match from the container through the bean type. When multiple identical bean types are matched, an error will be reported.

<bean id="userService" class="com.test.service.impl.UserServiceImpl" autowire="byType">

5. Other configuration tags of Spring

Spring's xml tags are generally divided into two categories, one is the default tag and the other is the custom tag.

type describe
Default label That is, there is no need to import additional tags with other namespace constraints, such as <bean>tags
Custom labels It is necessary to introduce other namespace constraints and refer to labels through prefixes, such as <context:property-placeholder/>labels

Spring's default tag uses Spring's default namespace

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

The default labels under this namespace constraint are as follows:

Label effect
<beans> Generally used as the xml configuration root tag, other tags are sub-tags of this tag
<bean> Bean configuration tags have been explained in detail above and will not be elaborated here.
<import> External resource import tag
<alias> Specifies the alias label of the Bean, which is less commonly used

<beans>Tags, in addition to being commonly used as root tags, can also be nested within the root tag and use the profile attribute to switch the development environment.

The activated environment can be specified in the following two ways:
using command line dynamic parameters , loading virtual machine parameter locations -Dspring.profiles.active=test
using code to set environment variables , System.setProperty("spring.profiles.active" ,"test")

<!-- 配置测试环境下,需要加载的Bean实例 -->
<beans profile="test"></beans>
<!-- 配置开发环境下,需要加载的Bean实例 -->
<beans profile="dev"></beans>

<import>Tags are used to import other configuration files. When the project becomes larger, there will be too much content in one configuration file. You can split a configuration file according to a certain part of the business. After splitting, it is finally imported into a main configuration file through tags <import>. , the project loads the main configuration file together with <import>the imported files.

<!--导入用户模块配置文件-->
<import resource="classpath:applicationContext-user.xml"/>
<!--导入商品模块配置文件-->
<import resource="classpath:applicationContext-orders.xml"/>

<alias>The label is to add an alias to a certain Bean. In the <bean>same way as using the name attribute to add an alias on the label, we specify four aliases for UserServiceImpl: aaa, bbb, xxx, yyy

<!--配置UserService-->
<bean id="userService" name="aaa,bbb" class="com.test.service.impl.UserServiceImpl">
     <property name="userDao" ref="userDao"/>
</bean>
<!--指定别名-->
<alias name="userService" alias="xxx"/>
<alias name="userService" alias="yyy"/>

Breakpoint debugging, a Map<String,String> collection named aliasMap is maintained in the beanFactory to store the mapping relationship between aliases and beanName.
Insert image description here
Spring's custom tags need to introduce external namespaces and specify external namespaces. Prefix, using tags in the form of <prefix:tag>, is called a custom tag. The parsing process of custom tags is also one of the Spring xml extension point methods. It will be introduced in detail in the subsequent chapter on integrating third-party frameworks.

<!--默认标签-->
<bean id="userDao" class="com.test.dao.impl.UserDaoImpl"/>
<!--自定义标签-->
<context:property-placeholder/>
<mvc:annotation-driven/>
<dubbo:application name="application"/>

Guess you like

Origin blog.csdn.net/ChennyWJS/article/details/132036420
Recommended