Spring Bean
Spring Bean
构建示例
User
@Data
public class User {
private String name;
private Integer age;
}
import com.fly.demo.User;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Map;
/**
* 构建示例:
* 1.通过 BeanDefinitionBuilder 构建
* 2.通过 AbstractBeanDefinition {@link AbstractBeanDefinition}以及派生类
*/
public class BeanDefinitionCreationDemo {
public static void main(String... args) {
// 1.通过 BeanDefinitionBuilder 构建
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder
.addPropertyValue("name", "fly")
.addPropertyValue("age", 12);
BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
// 2.通过 AbstractBeanDefinition 以及派生类
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
// 设置 Bean 类型
genericBeanDefinition.setBeanClass(User.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues
.add("name", "fly2")
.add("age", 13);
genericBeanDefinition.setPropertyValues(propertyValues);
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册
applicationContext.registerBeanDefinition("user", beanDefinition);
applicationContext.registerBeanDefinition("user2", genericBeanDefinition);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 获取bean
Map<String, User> stringUserMap = applicationContext.getBeansOfType(User.class);
System.out.println(stringUserMap); // {user=User{name='fly', age=12}, user2=User{name='fly2', age=13}}
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
Bean 别名示例
/**
* Bean 别名示例
*/
public class BeanAliasDemo {
public static void main(String... args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(BeanAliasDemo.class);
applicationContext.refresh();
User user = applicationContext.getBean("user", User.class);
User flyUser = applicationContext.getBean("fly-user", User.class);
System.out.println(user);
System.out.println("fly-user 是否与 user Bean 相同:" + (user == flyUser));
applicationContext.close();
}
@Bean(name = {"user", "fly-user"})
public User user() {
User user = new User();
user.setName("fly");
user.setAge(12);
return user;
}
}
注解 BeanDefinition 示例
import com.fly.demo.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/**
* 注解 BeanDefinition 示例
*/
@Import(AnnotationBeanDefinitionDemo.Config.class)
public class AnnotationBeanDefinitionDemo {
public static void main(String... args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(AnnotationBeanDefinitionDemo.class);
// 通过 BeanDefinition 注册 API 实现
// 1.命名 Bean 的注册方式
registerUserBeanDefinition(applicationContext, "fly-user");
// 2. 非命名 Bean 的注册方法
registerUserBeanDefinition(applicationContext, null);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 按照类型依赖查找
System.out.println("Config 类型的所有 Beans" + applicationContext.getBeansOfType(Config.class));
System.out.println("User 类型的所有 Beans" + applicationContext.getBeansOfType(User.class));
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
private static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder.addPropertyValue("name", "fly")
.addPropertyValue("age", 12);
if (StringUtils.hasText(beanName)) {
registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
} else {
// 非命名 Bean 注册方法
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);
}
}
// @Component
public static class Config {
@Bean
public User user() {
return new User();
}
}
@Bean
public User user() {
return new User();
}
}
单体 Bean 注册实例
import com.fly.demo.User;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
/**
* 单体 Bean 注册实例
* SingletonBeanRegistry#registerSingleton
*/
public class SingletonBeanRegistrationDemo {
public static void main(String... args) {
// 创建 BeanFactory 容器
AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext();
User user = new User();
SingletonBeanRegistry singletonBeanRegistry = applicationContext.getBeanFactory();
// 注册外部单例对象
singletonBeanRegistry.registerSingleton("user", user);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 通过依赖查找的方式来获取 user
User userByLookup = applicationContext.getBean("user", User.class);
System.out.println("user == userByLookup : " + (user == userByLookup));
// 关闭 Spring 应用上下文
applicationContext.close();
}
}
实例化 Spring Bean
Bean 实例化(Instantiation)
- 常规方式
- 通过构造器(配置元信息:XML、Java 注解和 Java API )
- 通过静态工厂方法(配置元信息:XML 和 Java API )
- 通过 Bean 工厂方法(配置元信息:XML和 Java API )
- 通过 FactoryBean(配置元信息:XML、Java 注解和 Java API )
- 特殊方式
- 通过 ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和 Java API )
- 通过 AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
- 通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
META-INF/bean-instantiation-context.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 -->
<bean id="user-by-static-method" class="com.fly.demo.User" factory-method="createUser"/>
<!-- 实例(Bean)方法实例化 Bean -->
<bean id="user-by-instance-method" factory-bean="userFactory" factory-method="createUser"/>
<bean id="userFactory" class="com.fly.demo.DefaultUserFactory"/>
<!-- FactoryBean实例化 Bean -->
<bean id="user-by-factory-bean" class="com.fly.demo.UserFactoryBean"/>
</beans>
User
@Data
public class User {
private String name;
private Integer age;
public static User createUser() {
User user = new User();
user.setName("default");
user.setAge(0);
return user;
}
}
UserFactory
/**
* 工厂类
*/
public interface UserFactory {
default User createUser() {
return User.createUser();
}
}
DefaultUserFactory
public class DefaultUserFactory implements UserFactory {
}
UserFactoryBean
import org.springframework.beans.factory.FactoryBean;
public class UserFactoryBean implements FactoryBean {
@Override
public User getObject() throws Exception {
return User.createUser();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
Bean 实例化示例
import com.fly.demo.User;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Map;
/**
* Bean 实例化示例
*/
public class BeanInstantiationDemo {
public static void main(String...args){
String location = "classpath:/META-INF/bean-instantiation-context.xml";
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(location);
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
System.out.println(userMap);
}
}
ServiceLoader
META-INF/services/com.fly.demo.UserFactory
# com.fly.demo.DefaultUserFactory 的 接口实现
com.fly.demo.DefaultUserFactory
import com.fly.demo.UserFactory;
import java.util.ServiceLoader;
/**
* META-INF/services/接口className
* 内容为接口的实现类className
*/
public class ServiceLoaderDemo {
public static void main(String... args) {
ServiceLoader<UserFactory> serviceLoader =
ServiceLoader.load(UserFactory.class, ServiceLoaderDemo.class.getClassLoader());
for (UserFactory userFactory : serviceLoader) {
System.out.println(userFactory.createUser());
}
}
}
特殊的 Bean 实例化示例
META-INF/special-bean-instantiation-context.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="userFactoryServiceLoader"
class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
<property name="serviceType" value="com.fly.demo.UserFactory"/>
</bean>
</beans>
import com.fly.demo.DefaultUserFactory;
import com.fly.demo.UserFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ServiceLoader;
/**
* 特殊的 Bean 实例化示例
*/
public class SpecialBeanInstantiationDemo {
public static void main(String...args){
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/special-bean-instantiation-context.xml");
ServiceLoader<UserFactory> serviceLoader = applicationContext.getBean("userFactoryServiceLoader", ServiceLoader.class);
for (UserFactory userFactory : serviceLoader) {
System.out.println(userFactory.createUser());
}
// 通过 AutowireCapableBeanFactory 创建
AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
UserFactory userFactory = autowireCapableBeanFactory.createBean(DefaultUserFactory.class);
System.out.println(userFactory.createUser());
}
}
初始化 Spring Bean
Bean 初始化(Initialization)
- @PostConstruct 标注方法
- 实现 InitializingBean 接口的 afterPropertiesSet() 方法
- 自定义初始化方法
- XML 配置:<bean init-method=”init” ... />
- Java 注解:@Bean(initMethod=”init”)
- Java API:AbstractBeanDefinition#setInitMethodName(String)
延迟初始化 Spring Bean
Bean 延迟初始化(Lazy Initialization)
- XML 配置:<bean lazy-init=”true” ... />
- Java 注解:@Lazy(true)
销毁 Spring Bean
Bean 销毁(Destroy)
- @PreDestroy 标注方法
- 实现 DisposableBean 接口的 destroy() 方法
- 自定义销毁方法
- XML 配置:<bean destroy=”destroy” ... />
- Java 注解:@Bean(destroy=”destroy”)
- Java API:AbstractBeanDefinition#setDestroyMethodName(String)
import com.fly.demo.UserFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class FlyUserFactory implements UserFactory, InitializingBean, DisposableBean {
@PostConstruct
public void init() {
System.out.println("@PostConstruct : UserFactory 初始化中...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中...");
}
public void initUserFactory() {
System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中...");
}
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy : UserFactory 销毁中...");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean#destroy() : UserFactory 销毁中...");
}
public void doDestroy() {
System.out.println("自定义销毁方法 doDestroy() : UserFactory 销毁中...");
}
@Override
protected void finalize() throws Throwable {
System.out.println("当前 DefaultUserFactory 对象正在被垃圾回收...");
}
}
import com.fly.demo.UserFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
public class BeanInitializationDemo {
public static void main(String... args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(BeanInitializationDemo.class);
applicationContext.refresh();
System.out.println("Spring 应用上下文已启动...");
UserFactory userFactory = applicationContext.getBean(UserFactory.class);
System.out.println(userFactory.createUser());
System.out.println("Spring 应用上下文准备关闭...");
// 关闭 Spring 应用上下文
applicationContext.close();
System.out.println("Spring 应用上下文已关闭...");
//@PostConstruct : UserFactory 初始化中...
//InitializingBean#afterPropertiesSet() : UserFactory 初始化中...
//自定义初始化方法 initUserFactory() : UserFactory 初始化中...
//Spring 应用上下文已启动...
//User(name=default, age=0)
//Spring 应用上下文准备关闭...
//@PreDestroy : UserFactory 销毁中...
//DisposableBean#destroy() : UserFactory 销毁中...
//自定义销毁方法 doDestroy() : UserFactory 销毁中...
//Spring 应用上下文已关闭...
//
//Process finished with exit code 0
// ---------------------------------------------------------------
// lazy 延迟初始化 ,getBean才会初始化
//Spring 应用上下文已启动...
//@PostConstruct : UserFactory 初始化中...
//InitializingBean#afterPropertiesSet() : UserFactory 初始化中...
//自定义初始化方法 initUserFactory() : UserFactory 初始化中...
//User(name=default, age=0)
//Spring 应用上下文准备关闭...
//@PreDestroy : UserFactory 销毁中...
//DisposableBean#destroy() : UserFactory 销毁中...
//自定义销毁方法 doDestroy() : UserFactory 销毁中...
//Spring 应用上下文已关闭...
}
@Bean(initMethod = "initUserFactory", destroyMethod = "doDestroy")
@Lazy
public UserFactory userFactory(){
return new FlyUserFactory();
}
}
垃圾回收 Spring Bean
Bean 垃圾回收(GC)
- 关闭 Spring 容器(应用上下文)
- 执行GC
- Spring Bean 覆盖的 finalize() 方法被回调
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Bean 垃圾回收(GC)示例
*/
public class BeanGarbageCollectionDemo {
public static void main(String...args) throws InterruptedException {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(BeanInitializationDemo.class);
applicationContext.refresh();
// 关闭 Spring 应用上下文
applicationContext.close();
Thread.sleep(5000L);
// 强制触发 GC
System.gc();
Thread.sleep(5000L);
}
}