这篇文章主要介绍了JavaBean和SpringBean的区别及创建SpringBean方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
正文
JavaBean和SpringBean的区别及创建SpringBean方式
一:对象,JavaBean,SpringBean的区别
1.什么是JavaBean
javaBean要求所有属性为私有,该类必须有一个公共无参构造函数,private属性必须提供公共的Getter setter给外部访问
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * @author yzh * @date 2021/4/29 8:42 **/public class User { //javaBean要求所有属性为私有,该类必须有一个公共无参构造函数,private属性必须提供公共的Getter setter给外部访问 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }} |
2.什么是SpringBean
SpringBean是受Spring管理的对象,所有能受Spring管理的对象都可以是SpringBean
3.SpringBean和JAVABean的区别
- 用处不同:传统javabean更多地作为值传递参数,而spring中的bean用处几乎无处不在,任何组件都可以被称为bean
- 写法不同:传统javabean作为值对象,要求每个属性都提供getter和setter方法;但spring中的bean只需为接受设值注入的属性提供setter方法
生命周期不同:传统javabean作为值对象传递,不接受任何容器管理其生命周期;spring中的bean有spring管理其生命周期行为
二:如何定义一个SpringBean
准备工作:引入Spring依赖包
|
1
2
3
4
5
6
|
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.14.RELEASE</version></dependency> |
1.通过ClassPathXmlApplicationContext
通过ClassPathXmlApplicationContext需要指定configLocation,所有我们现在resources目录下新建一个Spring.xml文件
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?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-3.2.xsd"> <!-- 使用设值注入方式装配实例 --> <bean id="user1" class="org.example.bean.User"> <property name="name" value="zhangsan" /> </bean> <!-- 使用构造方法装配实例 --> <!--使用构造方法装配需要在相应类提供构造函数--> <bean id="user2" class="org.example.bean.User"> <constructor-arg index="0" value="lisi" /> </bean></beans> |
同时相应对象重写toString方法,便于更好观察user1和user2
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package org.example.bean;/** * @author yzh * @date 2021/4/29 8:42 **/public class User { //javaBean要求所有属性为私有,该类必须有一个公共无参构造函数,private属性必须提供公共的Getter setter给外部访问 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public User(String name) { this.name = name; } public User() { } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; }} |
运行测试类
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package org.example.bean;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author yzh * @date 2021/4/29 8:45 **/public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(); classPathXmlApplicationContext.setConfigLocation("Spring.xml"); classPathXmlApplicationContext.refresh(); User user1 = classPathXmlApplicationContext.getBean("user1",User.class); System.out.println(user1); User user2 = classPathXmlApplicationContext.getBean("user2", User.class); System.out.println(user2); }} |
运行结果如下
User{name='zhangsan'}
User{name='lisi'}
2.通过AnnotationConfigApplicationContext底层
也是通过BeanDefinition实现
*@Bean@Component@Service@Controller都可以;一般@Service用于Service层,@Controller用于Controller层,此处以@Bean为例
新建一个Config类,并给User打上@Bean标签
|
1
2
3
4
5
6
7
8
9
10
11
12
|
package org.example.bean;import org.springframework.context.annotation.Bean;/** * @author yzh * @date 2021/4/29 9:20 **/public class Config { @Bean public User user(){ return new User(); }} |
通过AnnotationConfigApplicationContext获取bean,并打印bean对象
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package org.example.bean;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author yzh * @date 2021/4/29 8:45 **/public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); annotationConfigApplicationContext.register(Config.class); annotationConfigApplicationContext.refresh(); User user = annotationConfigApplicationContext.getBean("user",User.class); System.out.println(user); }} |
运行结果
User{name='null'}
3.通过BeanDefinition
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package org.example.bean;import org.springframework.beans.factory.support.AbstractBeanDefinition;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author yzh * @date 2021/4/29 8:45 **/public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); //定义一个Bean beanDefinition.setBeanClass(User.class); //把生成的Bean注册到容器中 annotationConfigApplicationContext.refresh(); annotationConfigApplicationContext.registerBeanDefinition("userTest",beanDefinition); User userTest = annotationConfigApplicationContext.getBean("userTest", User.class); System.out.println(userTest); }} |
运行结果
User{name='null'}
4.通过FactoryBean
4.1通过FactoryBean与注解方式
首先新建一个Person类
|
1
2
3
4
5
6
7
8
|
package org.example.bean;import org.springframework.stereotype.Component;/** * @author yzh * @date 2021/4/29 10:00 **/public class Person {} |
然后新建一个PersonFactoryBean类,并实现FactoryBean接口,重写其方法,为其打上@component注解, 此处和在Person类上打注解是同一效果
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package org.example.bean;import org.springframework.beans.factory.FactoryBean;import org.springframework.stereotype.Component;/** * @author yzh * @date 2021/4/29 10:01 **/@Component("person")public class PersonFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { return new Person(); } @Override public Class<?> getObjectType() { return Person.class; }} |
其次添加一个Config类打上@ComponentScan("org.example.bean"),目的是为了扫描包下的注解
|
1
2
3
4
5
6
7
8
9
|
package org.example.bean;import org.springframework.context.annotation.ComponentScan;/** * @author yzh * @date 2021/4/29 9:20 **/@ComponentScan("org.example.bean")public class Config {} |
最后通过AnnotationConfigApplicationContext获取Bean
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package org.example.bean;import org.springframework.beans.factory.support.AbstractBeanDefinition;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author yzh * @date 2021/4/29 8:45 **/public class Main { public static void main(String[] args) { //Config类为包扫描配置类 AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class); Person person = annotationConfigApplicationContext.getBean("person", Person.class); System.out.println(person); }} |
运行结果
org.example.bean.Person@28ac3dc3
4.2通过Factory和BeanDefinition
1.同4.1一样新建一个Person类
2.同4.1一样新建一个PersonFactoryBean类,实现FactoryBean接口,但是不打注解
3.通过BeanDefinition获取对象
此处和注解生成的差别在于通过BeanDefinition注册的会生成两个Bean对象,一个是person对应的类型是Person,另一个是&person对应的类型是PersonFactoryBean,通过下面代码的getBean方法可以看出来!!
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package org.example.bean;import org.springframework.beans.factory.support.AbstractBeanDefinition;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author yzh * @date 2021/4/29 8:45 **/public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); ////定义一个Bean beanDefinition.setBeanClass(PersonFactoryBean.class); //把生成的Bean注册到容器中 //annotationConfigApplicationContext.refresh(); //此处会生成2个Bean对象 第一个对象为&person对应的类型的PersonFactoryBean 第二个对象为person对应的类型为Person; annotationConfigApplicationContext.registerBeanDefinition("person",beanDefinition); PersonFactoryBean personFactoryBean = annotationConfigApplicationContext.getBean("&person", PersonFactoryBean.class); System.out.println(personFactoryBean); Person person = annotationConfigApplicationContext.getBean("person", Person.class); System.out.println(person); }} |
运行结果如下
org.example.bean.PersonFactoryBean@3aeaafa6
org.example.bean.Person@76a3e297
注
FactoryBean接口提供三个方法,但是我们重写了两个方法,这是因为另外一个方法是默认实现了的
FactoryBean接口方法如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package org.springframework.beans.factory;import org.springframework.lang.Nullable;public interface FactoryBean<T> { String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType"; @Nullable T getObject() throws Exception; @Nullable Class<?> getObjectType(); //默认实现方法,是否是单例 default boolean isSingleton() { return true; }} |
5.通过Supplier
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package org.example.bean;import org.springframework.beans.factory.support.AbstractBeanDefinition;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.function.Supplier;/** * @author yzh * @date 2021/4/29 8:45 **/public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); annotationConfigApplicationContext.refresh(); annotationConfigApplicationContext.registerBean(User.class, new Supplier<User>() { @Override public User get() { User user = new User(); user.setName("123"); return user; } }); User user = annotationConfigApplicationContext.getBean("user", User.class); System.out.println(user); }} |
bean的注入方式本文只是提供了多种api,很多情况下底层其实用的都是一样的东西,只是提供了不同的使用方式,具体可以通过源码查看。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持米米素材网。
原文链接:https://www.jianshu.com/p/2e6e07e59599

发表评论