On the Execution Sequence of @ Value and @ Bean

  • 2021-09-16 07:03:12
  • OfStack

Problem description

Using @ Autowired to process multiple bean of the same type, there is a problem with the execution order of @ Value and @ Bean.

First, use scan package + annotation to register different bean of User type, which are user and user1 respectively. The registration method is as follows


package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    private Integer id;
    private String name;
}

In this way, bean named user of User type is obtained


package com.fanyinhang.config;
import com.fanyinhang.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value={"com.fanyinhang.dao"})
public class AnnotationConfig {
    @Bean()
    public User user1(){
        return new User(2," Li 4");
    }
}

The UserDao configuration is as follows:


package com.fanyinhang.dao;
import com.fanyinhang.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:17
 */
@Repository
public class UserDao {
    @Autowired()
    private User user1;
    
    @Override
    public String toString() {
        return "UserDao{" +
                "user1=" + user1 +
                '}';
    }
}

import com.fanyinhang.config.AnnotationConfig;
import com.fanyinhang.dao.UserDao;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:18
 */
public class Test3 {
    @Test
    public void testAutowired(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationConfig.class);
        UserDao userDao = context.getBean(UserDao.class);
        System.out.println(userDao);
    }
}

The output is as follows:

UserDao {user1=User (id=2, name=Li 4)}

No problem without @ Value annotation, but after @ Value is added,


package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    @Value("1")
    private Integer id;
    @Value(" Zhang 3")
    private String name;
}

After running the testWired method again,

The result output is as follows:

UserDao {user1=User (id=1, name=Zhang 3)}

Why is this happening?

At first, I couldn't figure it out. Most of the information on the Internet said that @ Bean and @ Value had the order of execution.

To verify this statement, do a comparative test

One @ Value ("Zhang 3") has been removed


package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    @Value("1")
    private Integer id;
    //@Value(" Zhang 3")
    private String name;
}

The result output is as follows:

UserDao {user1=User (id=1, name=Li 4)}

Causes of the problem

When @ Value and @ Bean are under different files, @ Bean executes before @ Value. This will invalidate the value injected by @ Bean.

Solution

When @ Value and @ Bean are under different files, @ Value executes before @ Bean, so I made the following settings

Remove the @ Value annotation under User. java and place the @ Value annotation under the @ bean same file


package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    private Integer id;
    private String name;
}

package com.fanyinhang.config;
import com.fanyinhang.bean.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value={"com.fanyinhang.dao"})
public class AnnotationConfig {
    @Bean()
    public User user1(@Value("1") Integer id,@Value(" Zhang 3") String name){
        return new User(2," Li 4");
    }
}

At this time, run the test mode again, and the output result is as follows:

UserDao {user1=User (id=2, name=Li 4)}

Summarize


Related articles: