JavaBean和SpringBean的區別及創建SpringBean方式
一:對象,JavaBean,SpringBean的區別
1.什麼是JavaBean
javaBean要求所有屬性為私有,該類必須有一個公共無參構造函數,private屬性必須提供公共的Getter setter給外部訪問
/** * @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依賴包
<!-- 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文件
<?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
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 + '\'' + '}'; } }
運行測試類
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標簽
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對象
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
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類
package org.example.bean; import org.springframework.stereotype.Component; /** * @author yzh * @date 2021/4/29 10:00 **/ public class Person { }
然後新建一個PersonFactoryBean類,並實現FactoryBean接口,重寫其方法,為其打上@component註解, 此處和在Person類上打註解是同一效果
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”),目的是為瞭掃描包下的註解
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
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方法可以看出來!!
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接口方法如下:
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
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,很多情況下底層其實用的都是一樣的東西,隻是提供瞭不同的使用方式,具體可以通過源碼查看。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Spring容器中添加bean的5種方式
- @ComponentScan在spring中無效的原因分析及解決方案
- Java Spring框架創建項目與Bean的存儲與讀取詳解
- 詳解SpringBean基於XML的裝配
- Java 中的控制反轉(IOC)詳解