Java Bean 和 Spring Bean 的几种定义
文章目录
Java Bean 和 Spring Bean
Bean 就是对象。
不管是 Java Bean 还是 Spring Bean,都是为了获取实例化对象。其中的区别,本章博客采取代码案例说明。
Java Bean
Java Bean 即 Java 对象,在Java 中,定义一个对象采取new
实例化操作。
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
User user = new User();
user.setName("香蕉");
System.out.println(user.getName());
}
}
Spring Bean
测试使用 Spring Bean,则需要引入Spring依赖文件。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
XML创建bean
创建一个User.java类
package cn.linkpower.xml;
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在resources
文件下创建spring.xml
文件,并配置指定的Bean。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 1、定义bean(根据User中的构造方法生成bean对象)-->
<bean id="userBean" class="cn.linkpower.xml.User"></bean>
</beans>
创建测试类,将指定的spring.xml
文件加入至Spring容器中,实现对象的获取,设置值和调用等。
package cn.linkpower.xml;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
//classPathXmlApplicationContext.setConfigLocation("spring.xml");
User userBean = classPathXmlApplicationContext.getBean("userBean", User.class);
userBean.setName("香蕉");
System.out.println(userBean.getName());
// 验证Spring的bean是单例!
// User userBean2 = classPathXmlApplicationContext.getBean("userBean", User.class);
// userBean2.setName("香蕉2");
// System.out.println(userBean.getName());
// System.out.println(userBean2.getName());
// System.out.println(userBean.getName());
}
}
@Bean创建Bean
上面的操作,根据在xml中定义配置指定的bean对象,采取org.springframework.context.support.ClassPathXmlApplicationContext
将其加载至spring容器中,达到对象的生成和引用操作。
同时,也可以采取@Bean
实现对象的生成。
package cn.linkpower.beans;
import org.springframework.context.annotation.Bean;
public class UserConfig {
/**
* 采取 @Bean 的方式,构建一个 bean对象;<br/>
* 相当于 <bean id="getUser" class="cn.linkpower.beans.User" />
* @return
*/
@Bean
public User getUser(){
return new User();
}
}
使用AnnotationConfigApplicationContext
,将其加载至容器中。
测试类编写
package cn.linkpower.beans;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
// 构建容器
//AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
// 加载、注册配置类
// annotationConfigApplicationContext.register(UserConfig.class);
//annotationConfigApplicationContext.refresh();
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(UserConfig.class);
// 获取对象
User getUser = annotationConfigApplicationContext.getBean("getUser", User.class);
getUser.setName("banana");
System.out.println(getUser.getName());
}
}
@CompantScan创建Bean
上述的两种方式,都需要配置或者编写配置类的方式,定义或构建bean。如果对象过多,则需要配置的就较多。
除此之外,还能根据扫描操作实现类的定义操作。
编写扫描操作工具类(创建一个类,添加注解操作即可),当然,SpringBoot项目默认扫扫描启动类下目录:
package cn.linkpower.beanScan;
import org.springframework.context.annotation.ComponentScan;
/**
* @ComponentScan 注解,扫描的是带有 @Component 的类,将其解析加载至spring容器中
*/
@ComponentScan("cn.linkpower.beanScan")
public class UserConfigScan {
}
由于使用@ComponentScan
注解,是扫描指定路径
下,携带有@Component
标注的类,将其加载至Spring容器中,所以如果需要将类加载至Spring容器中,则需要在指定的类上添加Component
注解。
package cn.linkpower.beanScan;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
编写测试类:
package cn.linkpower.beanScan;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
// 这里主要是加载带有 @ComponentScan 注解的类,实现扫描 @Component 显示或隐式标注的类
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserConfigScan.class);
// 默认类名驼峰规范,所以此处从容器获取类,使用user
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
}
在Springboot中就广泛使用到@ComponentScan
。其次,类似@Service
等注解中也有@Component
的注解标注。
编程式BeanDefinition
在Spring构建bean对象时,采取xml 定义 bean
、@Bean 注解
、@Compant 注解
等方式,都属于声明式
创建bean对象。
Spring也支持编程式
创建实例对象,如下所示:
需要Spring构建实例化bean的类上
无注解
。
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
// 创建容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 执行一次refresh,否则报错
applicationContext.refresh();
// 描述一个bean
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
// 将描述的bean,设置别名称,放入容器中
applicationContext.registerBeanDefinition("userBeanObj",beanDefinition);
// 从容器中获取bean
User userBeanObj = applicationContext.getBean("userBeanObj", User.class);
System.out.println(userBeanObj);
}
}
在 Spring 源码中,不管是使用@Component
、@Bean
还是xml 配置<bean />
等,其底层的实现依旧还是采取的BeanDefinition
进行编程式构建。
除此之外,在BeanDefinition
中,还有其他属性参数可供类的设置,如单例、多例
等。
FactoryBean 构建bean
创建一个需要使用Spring实例化的类(无@Component注解
):
package cn.linkpower.factoryBean;
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
编写一个工厂类,为了生成bean:
package cn.linkpower.factoryBean;
import org.springframework.beans.factory.FactoryBean;
public class UserFactory implements FactoryBean {
/**
* 生成对象
* @return
* @throws Exception
*/
public Object getObject() throws Exception {
return new User();
}
/**
* 对象的类型
* @return
*/
public Class<?> getObjectType() {
return User.class;
}
}
编写测试类:
package cn.linkpower.factoryBean;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
// 1、构建容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
// 2、定义bean的修饰类
AbstractBeanDefinition abstractBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
// 添加一个类进去
abstractBeanDefinition.setBeanClass(UserFactory.class);
// 3、将已修饰的类放入容器中
applicationContext.registerBeanDefinition("userFactoryTest",abstractBeanDefinition);
//4、获取类
User user = applicationContext.getBean("userFactoryTest",User.class);
System.out.println(user);
// 这个是报错的!
//System.out.println(applicationContext.getBean("userFactoryTest",UserFactory.class));
// 如果想获取 UserFactory 对象,则需要 名称写为 &userFactoryTest
//System.out.println(applicationContext.getBean("&userFactoryTest",UserFactory.class));
}
}
[注意:]
使用
org.springframework.beans.factory.FactoryBean
修饰产生的bean,其实spring容器会将其生成两个bean对象。
userFactoryTest—> User 对象bean
&userFactoryTest—>UserFactory 类的对象bean
使用
org.springframework.beans.factory.FactoryBean
的getObject()
间接定义了一个bean。
Supplier 定义bean
在Spring框架中,存在使用Supplier构建bean的操作,在初始化生成bean时,可以通过Supplier类生成一个类初始的数据。其案例信息如下所示:
package cn.linkpower.supplier;
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
新建测试类:
package cn.linkpower.supplier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.function.Supplier;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
// 通过这种方式 注册bean
//applicationContext.registerBean(User.class);
applicationContext.registerBean(User.class, new Supplier<User>() {
public User get() {
User user = new User();
user.setName("banana");
return user;
}
});
User user = applicationContext.getBean("user", User.class);
System.out.println(user.getName());
}
}
代码参考
本文地址:https://blog.csdn.net/qq_38322527/article/details/113946325
推荐阅读
-
Spring的并发问题——有状态Bean和无状态Bean
-
品Spring:SpringBoot轻松取胜bean定义注册的“第一阶段”
-
Spring在代码中获取bean的几种方式详解
-
为什么整合Spring与Struts2的时候,必须定义Struts2 Bean的Scope
-
荐 java实训笔记_Spring中的bean
-
品Spring:SpringBoot轻松取胜bean定义注册的“第一阶段”
-
Spring5 - Bean的初始化和销毁的4种方式
-
[ SSH框架 ] Spring框架学习之二(Bean的管理和AOP思想)
-
Spring(18)——使用Java类的形式定义bean(二)
-
spring bean 的生命周期和配置源信息