Make writing a habit together! This is the 9th day of my participation in the “Gold Digging Day New Plan ยท April More text Challenge”. Click here for more details

  • Spring Reading Directory

Accumulate over a long period, constant dripping wears away a stone ๐Ÿ˜„

preface

The @bean is an annotation that is applied to methods (and can be used on annotations), and the method annotated by the @Bean generates a Bean managed by the Spring container.

@beans are equivalent to the < Bean /> tag in an XML file. @beans need to be used with @Component or @Configuration, usually with @Configuration (think of it), as follows:

@Configuration
public class BeanConfig {
    @Bean
    public UserServiceImpl u(a){
        return newUserServiceImpl(); }}Copy the code

The source code to define

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {

	BeanName is the alias of name. In the absence of other attributes, beanName can be specified as follows
    // @Bean("u")
	@AliasFor("name")
	String[] value() default {};

	// Specify beanName. If not, use the method name beanName
    // If multiple names are specified, the first name is beanName and the others are aliases
	@AliasFor("value")
	String[] name() default {};

	BY_NAME: according to beanName * Autowire.BY_TYPE: according to beanName * Autowire. This attribute is deprecated. Do not mind using */
	@Deprecated
	Autowire autowire(a) default Autowire.NO;

	// Whether this bean can be automatically assembled into other beans. Default is true
    // If false, it represents another bean and cannot be injected
	boolean autowireCandidate(a) default true;

	// The bean's initialization method, specifying the method name without parentheses
    // The default value is "", indicating that the initialization method is not called
	String initMethod(a) default "";

	// Specify the destruction method
	String destroyMethod(a) default AbstractBeanDefinition.INFER_METHOD;

}
Copy the code

For example,

value

public class UserServiceImpl {}@Bean({"u1","u2"})  // beanName is u1, alias u2
public UserServiceImpl u(a){
    return new UserServiceImpl();
}
Copy the code

autowireCandidate

The autowireCandidate property is set to false, and an error is reported when injected using @AutoWired in the ProductServiceImpl class.

@Bean(name = {"u1","u2"},autowireCandidate = false)
public UserServiceImpl u(a){
    return new UserServiceImpl();
}

@Component
public class ProductServiceImpl {

    @Autowired
    private UserServiceImpl userService;
}
Copy the code

initMethod

Specifies the initialization method, initMethod2.

@Bean(name = {"u1","u2"},initMethod = "initMethod2")
public UserServiceImpl u(a){
    return new UserServiceImpl();
}
Copy the code

Add the initMethod2 method to the UserServiceImpl class.

public void initMethod2(a){
    System.out.println("UserServiceImpl = initMethod2");
}
Copy the code

destroyMethod

Specify the destruction method, destroyMethod2.

@Bean(name = {"u1","u2"},initMethod = "initMethod2",destroyMethod = "destroyMethod2")
Copy the code

Add a destroyMethod2 method in the UserServiceImpl class.

public void destroyMethod2(a){
    System.out.println("UserServiceImpl = destroyMethod2");
}
Copy the code

When the container stops, the destroyMethod2 method is called. However, this method is called only if there are singleton beans, not if there are other scopes. If you add a public, no-argument method named ** “close” or “shutdown” to UserServiceImpl, this method will be called even if you do not specify destroyMethod. If you want to disable this, set the destroyMethod property value to “”.

@ComponentScan(basePackages = "com.cxyxj.beandemo")
public class AppMain {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppMain.class);

        // Print the bean name
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String name : beanDefinitionNames){
            System.out.println(name);
        }
        // Get the alias according to beanName
        String[] u1s = context.getAliases("u1");
        System.out.println("Alias" + Arrays.asList(u1s));
        // Close the containercontext.close(); }}Copy the code

Pay attention to the point

Note 1

Found that the @bean source definition does not have environment activation, Lazy loading, Scope, preferred Bean, or dependency Settings. It should be declared with @profile, @lazy @scope, @dependson, and @primary.

  • @profile: Specifies the environment in which the Bean can be registered in the container. If not specified, any environment can be registered in the Bean.

  • @scope changes the Scope of the bean from a singleton to a specified Scope.

  • @lazy is only practical if the default singleton scope is used.

  • DependsOn enforces the creation of a specific other bean before this bean is created.

  • The @primary indicates that the bean should be given priority when multiple candidates are eligible to auto-assemble a dependency

Note 2

We started by saying that @beans need to be used with @Component or @Configuration, usually @Configuration. What’s the difference between the two?

Used with @ Configuration

@Configuration
public class BeanConfig {

    @Bean(name = {"u1","u2"})
    public UserServiceImpl u(a){
        UserServiceImpl userService = new UserServiceImpl();
        System.out.println("userService = " + userService);
        return userService;
    }

    @Bean
    public ProductServiceImpl p(a){
        u();
        return newProductServiceImpl(); }}Copy the code
  • Start the class
@ComponentScan(basePackages = "com.cxyxj.beandemo")
public class AppMain {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = newAnnotationConfigApplicationContext(AppMain.class); }}Copy the code
  • Start the result

U () is only called once.

So when is it used twice?

  • If the Spring version is 5.2 or later, you need to ensure that the proxyBeanMethods attribute of @Configuration is true.

  • Methods annotated by @beans are static.

The result is that each call to the u() method produces a new instance.

Used with @ Component

It is not allowed to call with directly@BeanAnnotation method. Dependency injection is required.

Pay attention to point 3

Move the creation of ProductServiceImpl to UserServiceImpl.

@Bean
public static ProductServiceImpl p(a){
	return new ProductServiceImpl();
}
Copy the code

ProductServiceImpl cannot be injected into the container at this point. This is because Spring restricts the ability of beans injected by @beans to use the bean-creation function internally. For example: @bean, @import.


  • If you have any questions or errors in this article, please feel free to comment. If you find this article helpful, please like it and follow it.