對IoC容器和Bean的學習筆記

What We Mean by "Spring"

The term "Spring" means different things in different contexts. It can be used to refer to the Spring Framework project itself, which is where it all started. Over time, other Spring projects have been built on top of the Spring Framework. Most often, when people say "Spring", they mean the entire family of projects. This reference documentation focuses on the foundation: the Spring Framework itself.

Introduction

IoC,the Inversion of Control. IoC is also known as dependency injection (DI). (依賴注入實現了控制反轉,爲此Spring設計了The IoC Container這項技術)

It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

這段描述是關於"依賴注入"(Dependency Injection,DI)的解釋。依賴注入是軟件工程中的一種設計模式,它通過構造函數參數、工廠方法的參數或者在對象實例構造或從工廠方法返回後設置的屬性來定義對象的依賴關係。容器在創建對象時注入這些依賴。這個過程本質上是對象本身通過直接構造類或使用服務定位器模式等機制來控制其依賴項的實例化或定位的反轉(因此得名“控制反轉”)。

傳統上,對象可能會直接實例化或定位其所依賴的對象,導致緊耦合,並且難以修改或測試單個組件。依賴注入通過將依賴管理的責任從對象本身移交給外部容器或框架來解決這個問題。

應用依賴注入,對象可以更具可重用性和可維護性,因爲它們只關注履行自己的職責,而依賴關係從外部進行注入。這樣可以更好地分離關注點,並且可以更容易地修改依賴關係,而無需修改依賴對象。

通過依賴注入實現的控制反轉還有助於測試,因爲在單元測試期間,可以輕鬆地使用模擬對象替代依賴項,實現對各個組件的隔離測試。

總體而言,依賴注入是一種強大的技術,通過將依賴的創建和管理從依賴對象本身解耦,促進模塊化、松耦合和可測試的軟件設計。

The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container.

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

Container Overview

The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans.

In stand-alone applications, it is common to create an instance of ClassPathXmlApplicationContext or FileSystemXmlApplicationContext.

2023-07-20-19-08-30-image

Configuration Metadata

The configuration metadata is represented in XML, Java annotations, or Java code. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application.

XML-based metadata is not the only allowed form of configuration metadata. Other forms of metadata with the Spring container, see:

XML-based configuration metadata configures these beans as <bean/> elements inside a top-level <beans/> element. Java configuration typically uses @Bean-annotated methods within a @Configuration class.

<?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
		https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="..." class="...">
		<!-- collaborators and configuration for this bean go here -->
	</bean>

	<bean id="..." class="...">
		<!-- collaborators and configuration for this bean go here -->
	</bean>

	<!-- more bean definitions go here -->

</beans>

Instantiating a Container

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

services.xml

<?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
		https://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- services -->

	<bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
		<property name="accountDao" ref="accountDao"/>
		<property name="itemDao" ref="itemDao"/>
		<!-- additional collaborators and configuration for this bean go here -->
	</bean>

	<!-- more bean definitions for services go here -->

</beans>

The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition.

This linkage between id and ref elements expresses the dependency between collaborating objects.

daos.xml

<?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
		https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="accountDao"
		class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
		<!-- additional collaborators and configuration for this bean go here -->
	</bean>

	<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
		<!-- additional collaborators and configuration for this bean go here -->
	</bean>

	<!-- more bean definitions for data access objects go here -->

</beans>

Composing XML-based Configuration Metadata

Often, each individual XML configuration file represents a logical layer or module in your architecture.

Use one or more occurrences of the <import/> element to load bean definitions from another file or files. The following example shows how to do so:

<beans>
	<import resource="services.xml"/>
	<import resource="resources/messageSource.xml"/>
	<import resource="/resources/themeSource.xml"/>

	<bean id="bean1" class="..."/>
	<bean id="bean2" class="..."/>
</beans>

The Groovy Bean Definition DSL

beans {
	dataSource(BasicDataSource) {
		driverClassName = "org.hsqldb.jdbcDriver"
		url = "jdbc:hsqldb:mem:grailsDB"
		username = "sa"
		password = ""
		settings = [mynew:"setting"]
	}
	sessionFactory(SessionFactory) {
		dataSource = dataSource
	}
	myService(MyService) {
		nestedBean = { AnotherBean bean ->
			dataSource = dataSource
		}
	}
}

Using the Container

By using the method T getBean(String name, Class<T> requiredType), you can retrieve instances of your beans.

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();

Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation).

Bean Overview

Beans are created with the configuration metadata that you supply to the container (for example, in the form of XML <bean/> definitions).

Class只是Class,但是如果配置到了XML的<bean/>,那麼它就成爲了the Spring Bean。

BeanDefinition:

  • A package-qualified class name: typically, the actual implementation class of the bean being defined.

  • Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so forth).

  • References to other beans that are needed for the bean to do its work. These references are also called collaborators or dependencies.

  • Other configuration settings to set in the newly created object — for example, the size limit of the pool or the number of connections to use in a bean that manages a connection pool.

Naming Beans

In XML-based configuration metadata, you use the id attribute, the name attribute, or both to specify bean identifiers.

Aliasing a Bean outside the Bean Definition

<alias name="fromName" alias="toName"/>

Instantiating Beans

If you use XML-based configuration metadata, you specify the type (or class) of object that is to be instantiated in the class attribute of the <bean/> element.

Instantiation with a Constructor

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

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

Instantiation with a Static 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;
	}
}

Instantiation by Using an Instance Factory Method

<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
	<!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="clientService"
	factory-bean="serviceLocator"
	factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator {

	private static ClientService clientService = new ClientServiceImpl();

	public ClientService createClientServiceInstance() {
		return clientService;
	}
}

In Spring documentation, "factory bean" refers to a bean that is configured in the Spring container and that creates objects through an instance or static factory method.

Determining a Bean’s Runtime Type

The recommended way to find out about the actual runtime type of a particular bean is a BeanFactory.getType call for the specified bean name.

參考資料:

The IoC Container https://docs.spring.io/spring-framework/reference/core/beans.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章