目录

1、bean是什么

2、配置bean

2.1、使用@Bean注解配置Bean

2.2、使用@Import注解配置Bean

 3、实例化Bean

1、bean是什么

        在 Spring 中,Bean 是指由 Spring 容器管理的对象。Spring IOC 容器负责创建、配置和管理这些 Bean 对象的生命周期。Spring IOC 容器会管理应用程序中的组件,并通过依赖注入(DI)将它们组装在一起。Bean 是应用程序的核心构建块,它们通常代表应用程序中的各种对象,例如服务、数据访问对象(DAO)、控制器等。

        要在 Spring 中使用 Bean,通常需要在 Spring 配置文件(如 XML 文件)或使用注解(@Component)来声明 Bean,并告诉 Spring 容器如何创建和配置它们。一旦 Bean 被声明和配置好,Spring 容器将负责实例化它们,并在需要时将它们注入到其他 Bean 中。

        简单来说就是:在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。bean 是由Spring IoC 容器实例化、组装和管理的对象。

 

2、配置bean

        配置bean可以通过在 xml 文件中用 这个标签的方式来进行显式的声明,但是这种方式太麻烦了。

        所以现在都是通过 @component注解 来把类配置成bean,在类级别上使用 @Component 注解或其派生注解(@Service、@Repository、@Controller 等)就可以将一个类声明为 Bean

        这两种配置方式可以看这一篇:【Spring】分别基于XML、注解和配置类实现Spring的IOC(控制反转)-CSDN博客

这里主要是使用@Bean和@Import注解配置Bean

2.1、使用@Bean注解配置Bean

@Bean 特性:

一、是放在方法上面的

二、必须放在配置类里面

        @Bean方法调用另外一个@Bean方法,会从spring容器中去获取

三、@Bean可以干预bean的实例化过程的,而且jar包中的类如果要配置bean就需要用@Bean

四、在这个方法中声明的参数,spring也会帮我们自动注入进来

相关代码:

//接口IUserDao

public interface IUserDao {

//执行查询用户

void getUser();

}

//接口IUserDao的实现类UserDao

public class UserDao implements IUserDao {

@Override

//执行查询用户

public void getUser() {

System.out.println("Holle Spring");

}

}

//接口IUserService

public interface IUserService {

void getUser();

}

//接口IUserService的实现类UserService

//@Service

public class UserService implements IUserService {

@Autowired

IUserDao userDao;

@Override

public void getUser() {

userDao.getUser();

}

}

//配置类SpringConfig

@Configuration

public class SpringConfig {

@Bean //使用@Bean配置UserService成为bean

public IUserService userService(){

IUserDao userDao = UserDao();

UserService userService = new UserService();

return userService;

}

@Bean //使用@Bean配置UserDao成为bean

public IUserDao UserDao(){

return new UserDao();

}

}

//测试类C3IocApplicationTests

@SpringBootTest

class C3IocApplicationTests {

@Autowired

IUserService userService;

@Test

void contextLoads() {

userService.getUser();

}

}

2.2、使用@Import注解配置Bean

@lmport 特性:

一、@lmport必须写在类上面,不能用于方法等其他的上面

二、标记的类必须是一个bean,否则不会起作用

 @lmport的三种使用方式

(1)普通类:就是直接@lmport(UserService.class)普通类,就会把这个普通类注入spring

示例:

(2)lmportSelector :用于根据完整限定名字符串批量注入Bean

        a、定义一个类实现lmportSelector

        b、批量注册bean(通过实现selectlmports,返回bean的完整类路径字符串数组)

        c、然后在配置类上加上@lmport(实现lmportSelector.class)

示例:

 

其他代码和上面使用@Bean的例子是一样的,实现了 ImportSelector 接口的 MyImportSelector 类代码:

public class MyImportSelector implements ImportSelector {

@Override

public String[] selectImports(AnnotationMetadata importingClassMetadata) {

return new String[]{

"com.lt.ioc.service.UserService",

"com.lt.ioc.dao.UserDao"

};

}

}

(3)ImportBeanDefinitionRegistrar

        定义一个类实现lmportBeanDefinitionRegistrar,然后在方法里根据beanDefinition注册bean

示例:和上面的 lmportSelector 用法一样,把实现了 ImportBeanDefinitionRegistrar 接口的类传递给@Import注解就可以

实现了 ImportBeanDefinitionRegistrar 接口的 MyImportBeanDefinitionRegistrar 类代码:

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {

//创建BeanDefinition,只有这个类的BeanDefinition存在了,才能根据这个BeanDefinition去创建类的bean对象

RootBeanDefinition definition = new RootBeanDefinition();

//把要创建bean的类的完整限定名传递给BeanDefinition

definition.setBeanClassName("com.lt.ioc.service.UserService");

//注册这个BeanDefinition

registry.registerBeanDefinition("userService",definition);

}

}

 3、实例化Bean

1、spring会默认使用无参构造器(无参构造函数)实例化

有多个构造函数依然会调用无参构造函数如果只有一个有参构造函数,spring就会调用这个有参构造函数,并且把参数自动装配进来如果有参构造函数有个多个,并且没有无参构造函数,那就会报错,因为spring不知道该选哪一个构造函数,这时候对spring来说,他需要一个默认的无参构造函数

2、使用实例工厂方法实例化--@Bean

可以自由的选择构造函数进行实例化

 

3、使用工厂Bean。实例化--FactoryBean

FactoryBean是一个接口需要有一个Bean,一旦这个Bean实现FaétoryBean就成为了特殊的Bean需要实现2个方法

        1)getObject() ---->当通过Bean实际名称获取到的就是getObject 返回的对象(伪装)

        2)getObjecType()---->想通过容器去获取对应(getObject 返回的对象)的类型,就需要返回getObject 返回的对象的类型

可以自由的选择构造函数进行实例化

示例:

OrderService类是加了@Service注解并且实现了FactoryBean接口的一个类,代码:

@Service

public class OrderService implements FactoryBean {

// 加了@Service注解并且实现了FactoryBean接口的OrderService变成了一个特殊的bean

// 特殊: 就是根据bean(这里是OrderService)的名字实际上是获取getObject方法返回的对象(狸猫换太子)

@Override

public Object getObject() throws Exception {//(这里getObject方法中返回的对象就是UserService)

return new UserService();

}

@Override

public Class getObjectType() {//想通过容器去获取对应(getObject 返回的对象)的类型,就需要返回getObject返回的对象的类型

return UserService.class;

}

}

获取容器,并分别通过FactoryBean接口中的两种方法从容器中获取UserService的bean和获取实现了FactoryBean接口的OrderService实际的Bean

//启动类C3IocApplication

@SpringBootApplication

public class IocApplication {

public static void main(String[] args) {

ConfigurableApplicationContext ioc = SpringApplication.run(IocApplication.class, args);

//OrderService是加了@Service注解并且实现了FactoryBean接口的一个类,他是一个特殊的bean

System.out.println(ioc.getBean("orderService"));//通过OrderService中重写了的getObject()方法来获取UserService的bean

System.out.println(ioc.getBean(UserService.class));//通过OrderService中重写了的getObjectType()方法来获取UserService的bean

//如果想获取FactoryBean实际的Bean可以 1.通过类型; 2.在beanName前加上&

System.out.println(ioc.getBean(OrderService.class));

System.out.println(ioc.getBean("&orderService"));

}

}

推荐: 

【Spring】分别基于XML、注解和配置类实现Spring的IOC(控制反转)-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137237805?spm=1001.2014.3001.5501

 【java多线程】通过等待唤醒机制、局部变量、原子变量实现线程同步-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137122461?spm=1001.2014.3001.5501

【java多线程】通过等待唤醒机制、局部变量、原子变量实现线程同步-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137122461?spm=1001.2014.3001.5501

文章链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。