Let's read the official documents together ----- SpringIOC (02)

1.3. Bean overview

The Spring IoC container manages one or more bean s. These bean s are created using configuration metadata that you provide to the container (for example, as XML definitions).

Within the container itself, these bean definitions are represented as BeanDefinition objects, which contain (amongst other information) the following metadata:

Package-qualified class name: Usually, the actual implementation class of the Bean is defined.
Bean behavior configuration element, used to declare the behavior of a bean in the container (scope, lifecycle callbacks, etc.).
A bean that references other beans to do its work. These references are also called collaborators or dependencies.
Additional configuration settings to set in the newly created object - for example, the size limit of the pool or the number of connections used in the Bean that manages the connection pool.

This metadata is translated into a set of properties that make up each bean definition. The following table describes these properties:

Attributes explain
kind instantiate the bean
name bean name
life cycle bean life cycle
Constructor parameters dependency injection
Attributes dependency injection
Automatic injection mode auto-injected collaborators
lazy initialization mode lazy initialization of bean s
initialization method initialization callback
Destruction method destroy callback

In addition to bean definitions that contain information about how to create a particular bean, these ApplicationContext implementations also allow existing objects created outside the container (by the user) to be registered. This is done by accessing the ApplicationContext's BeanFactory's getBeanFactory() method, which returns the BeanFactory's DefaultListableBeanFactory implementation. DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods. However, typical applications only use beans defined through regular bean definition metadata.

Custom class without any annotations
    public class LearnBean {
        public LearnBean(String name) {
        }
        public String getString(){
            return "learnSpring";
        }
    }

The first: AnnotationConfigApplicationContext self-contained registerBean method, which can be passed in class and construction parameters

    AnnotationConfigApplicationContext annotationConfigApplicationContext = 
                                new AnnotationConfigApplicationContext();
    annotationConfigApplicationContext.registerBean(LearnBean.class,"");
    annotationConfigApplicationContext.refresh();
    LearnBean bean = (LearnBean) annotationConfigApplicationContext.getBean("learnBean");
    System.out.println(bean.getString());

The second: can also be passed in class and beanDefinition That is, the configuration metadata this and getBeanFactory().registerBeanDefinition(..)is a meaning

    AnnotationConfigApplicationContext annotationConfigApplicationContext = 
                                new AnnotationConfigApplicationContext();

    RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(LearnBean.class);
    ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
    constructorArgumentValues.addIndexedArgumentValue(0,"111");
    rootBeanDefinition.setConstructorArgumentValues(constructorArgumentValues);
    annotationConfigApplicationContext.registerBeanDefinition("learnBean",rootBeanDefinition);

    annotationConfigApplicationContext.refresh();

    LearnBean bean = (LearnBean) annotationConfigApplicationContext.getBean("learnBean");
    System.out.println(bean.getString());


Note: if you do not write
    annotationConfigApplicationContext.refresh();
will report an error
Exception in thread "main" java.lang.IllegalStateException: org.springframework.context.annotation.AnnotationConfigApplicationContext@68de145 has not been refreshed yet
    at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1096)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108)
    at org.springframework.example.DebuggerSpringMain.main(DebuggerSpringMain.java:40)

Bean metadata and manually provided singleton instances need to be registered as early as possible so that the container can properly reason about them during autowiring and other introspection steps. While overriding existing metadata and existing singleton instances is supported to some extent, registration of new beans at runtime (concurrent with live access to the factory) is not officially supported and may result in concurrent access exceptions, bean The state in the container is inconsistent or both.

Apparently it's too late to register with Spring Basic step fusion, some dependency injection cannot be completed
1.3.1. bean naming

Each bean has one or more identifiers. These identifiers must be unique within the container hosting the Bean.
A bean usually has only one identifier. However, if more than one is required, the redundant aliases can be treated as aliases.

In an XML-based configuration file, you can use the id attribute, the name attribute, or both to specify the bean identifier. The id attribute allows you to specify exactly an ID. By convention, these names are alphanumeric ("myBean", "someService", etc.), but they can also contain special characters. If you want to introduce additional aliases for the bean, you can also specify them in the name attribute, separated by commas (,), semicolons (;), or spaces. As a historical note, in versions prior to Spring 3.1, the id property was defined as an xsd:ID type, which limited the possible characters. Since 3.1, it is defined as xsd:string type. Note that Bean id uniqueness is still enforced by the container, although no longer by the XML parser.

You do not need to provide a name or id for the bean. If no name or id is provided explicitly, the container will generate a unique name for the bean. However, if you wish to refer to that bean by name by using the ref element or service locator style lookup, then you must provide a name. Names are usually not required when using inner bean s with autowiring.

###### Bean naming convention
 convention is in naming bean will be standard Java Conventions are used for instance field names.
That is, bean The name starts with a lowercase letter and is camel-cased from there.
Examples of such names include accountManager, accountService,userDao,loginController,and many more.

Consistently named Bean Make your configuration easier to read and understand.
Also, if you use Spring AOP,then the pointcut is applied to a set of names related to bean , it will be helpful.

By doing component scanning in the classpath, Spring will be generated for unnamed components according to the rules described earlier Bean Name: Essentially, takes a simple class name and converts its initial characters to lowercase.
However, in the (unusual) special case, if there are multiple characters and the first and second characters are both uppercase, the original case is preserved.
These rules and java.beans.Introspector.decapitalize(Depend on Spring used here) defines the same rules.
Aliasing beans outside of Bean definitions

Within the bean definition itself, a bean can be given multiple names by using a combination of at most one name specified by the id attribute and any number of other names in the attribute. These names can be equivalent aliases for the same bean, and are useful in some cases, for example, to have every component in an application refer to a common dependency by using a bean name specific to the component itself.

However, specifying all aliases where the bean is actually defined is not always sufficient. It is sometimes necessary to introduce aliases for bean s defined elsewhere. This is often the case in large systems, where configuration is distributed among each subsystem, each with its own set of object definitions. In XML-based configuration metadata, you can use elements to accomplish this. The following example shows how to do this:

<alias name="fromName" alias="toName"/>
under these circumstances,(in the same container)named fromName of bean After using this alias definition, it can also be called as toName. 

E.g, Subsystem A's configuration metadata may reference a data source called subsystem-DataSource.
Subsystem B's configuration metadata can reference a data source named subsystembl-DataSource.
When writing the main application that uses these two subsystems, the main application references the data source under the name myApp-dataSource.
To have all three names refer to the same object, you can add the following alias definition to the configuration metadata:

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>

Now each component and main application can refer to the data source by a unique name and is guaranteed not to conflict with any other definition (effectively creating a namespace), but they refer to the same bean.

Java-configuration

If using Java-configuration, the @Bean annotation can be used to provide aliases. See Using the @Bean Annotation for details.

1.3.2. instantiate the bean

A bean definition is essentially a recipe for creating one or more objects. When requested, the container looks at the recipe for the named bean and uses the configuration metadata encapsulated by that bean definition to create (or get) the actual object.

If you use XML-based configuration metadata, you can specify the type (or class) of the object to instantiate in the element's class attribute. This class attribute (internally the instance's Class attribute BeanDefinition) is usually required.

The Class attribute is used in the following two situations:

Usually, the container itself is created directly by calling its constructor by reflection bean in the case of,
specify to construct bean class, which is somewhat equivalent to using new operator's Java code.

To specify the actual class that contains the static factory method called to create the object,
The container calls a static factory method on the class to create bean is less common.
The type of object returned from a static factory method call can be the same class or a different class entirely.
inner class name
 If you want to configure for static nested classes bean definition, you must use the binary name of the nested class.

For example, if you are com There is a class called what.
This class of things has a class called OtherThing the static nested class,
bean by definition class The value of the property will be com.example.SomeThing$OtherThing. 

Note that the name used $character to separate the nested class name from the outer class name.

<bean id="innerClass1" class="org.springframework.example.config.MyBean$InnerClass"/>
instantiate with constructor

All normal classes are available and compatible with Spring when creating a bean via the constructor. That is, the class under development does not need to implement any specific interface or be coded in a specific way. Just specifying the bean class is enough. However, depending on the type of IoC you are using for that particular bean, you may need a default (empty) constructor.

The Spring IoC container can manage almost any class you want to manage. It's not limited to managing real JavaBean s. Most Spring users prefer an actual JavaBean that just has a default (parameterless) constructor with appropriate setter s and getter s modeled after properties in the container. You can also have more fancy non-bean style classes in the container. For example, if you need to use an old-style connection pool that is definitely not JavaBean-compliant, Spring can manage that too.

Using XML-based configuration metadata, you can specify bean classes as follows:

<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

See Injecting Dependencies for details on the mechanism used to provide arguments to the constructor (if required) and set object instance properties after the object is constructed.

Instantiate with static factory method

When defining a bean created with a static factory method, use the class attribute to specify the class containing the static factory method, and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional parameters, as described later) and return a live object that will then be considered to have been created through the constructor. One use of this bean definition is to call static factories with legacy code.

The following bean definition specifies that the bean is created by calling the factory method. The definition does not specify the type (class) of the returned object, but only the class containing the factory method. In this example, the createInstance() method must be a static method. The following example shows how to specify a factory method:

<bean id="clientService"
    class="examples.ClientService"
    factory-method="createInstance"/>

public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}

    public static ClientService createInstance() {
        return clientService;
    }
}
Instantiate using an instance factory method

Similar to instantiating via a static factory method, instantiating with an instance factory method creates a new bean by calling a non-static method of an existing bean from the container. To use this mechanism, leave the class attribute blank and specify in the factory-bean attribute the name of the bean in the current (or parent or ancestor container) that contains the instance method of the object to be created. Use the factory-method attribute to set the name of the factory method itself. The following example shows how to configure such a Bean:

<bean id="serviceLocator" class="examples.DefaultServiceLocator">
</bean>

<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();

    public ClientService createClientServiceInstance() {
        return clientService;
    }
}

A factory class can also contain more than one factory method, as shown in the following example:

<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

<bean id="accountService"
    factory-bean="serviceLocator"
    factory-method="createAccountServiceInstance"/>

public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();

    private static AccountService accountService = new AccountServiceImpl();

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }
}

This approach shows that the factory Bean itself can be managed and configured via Dependency Injection (DI). For more information, see Dependencies and Configuration.

In the Spring documentation, "factory bean" refers to a bean that is configured in the Spring container and creates objects through an instance or static factory method. Instead, FactoryBean (note the capitalization) refers to the Spring-specific FactoryBean implementation class.

Determine the runtime type of a Bean

Determining the runtime type of a particular bean is not trivial. The specified class in the Bean metadata definition is just the initial class reference, which may be used in conjunction with the declared factory method, or the FactoryBean may cause the Bean's runtime type to be a different class, or in the case of an instance-level factory method not set at all ( resolved by specifying the factory-bean name). Additionally, AOP proxies can wrap bean instances with interface-based proxies, with limited exposure of the target bean's actual type (only the interface it implements).

The recommended way to find out the actual runtime type of a particular bean is to call BeanFactory.getType specifying the bean name. This takes all of the above into account and returns the type of object that BeanFactory.getBean is to return for the same bean name.

Posted by wiseone on Tue, 17 May 2022 15:29:01 +0300