一:對象,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