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)

  1. 关闭 Spring 容器(应用上下文)
  2. 执行GC
  3. 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);
    }
}
posted @ 2020-10-08 16:25  fly_bk  阅读(83)  评论(0编辑  收藏  举报