在 Spring中 创建 JavaBean
2019獨角獸企業重金招聘Python工程師標準>>>
在 Spring中 創建 JavaBean
Spring 框架的最核心功能之一是 DI (Dependency Injection), 也就是依賴注入。
DI 的底層原理是反射技術,對 JavaBean 的屬性進行賦值,從而達到 A 到 B 模塊的解耦。Spring 提供 DI 容器,對需要關聯的 JavaBean、不需要關聯的 JavaBean 的創建、銷毀都要進行統一的調度和管理。
在我們的程序中,我們將不使用 new 關鍵字的創建對象,而是交給 DI 容器管理生命周期,以及多個 JavaBean 之間的注入關系。從技術上說,就是使用反射將接口和實現相分離。
但在此之前,我們來看看如何使用 Spring 框架,以及幾種創建 JavaBean 的方式。
1. 不使用 Spring 框架的傳統方式
先創建一個 Java Project,創建一個保存操作的類 Save
package save;public class Save {public void save() {System.out.println("save 方法!");} }一個測試類 Test
package test;import save.Save;public class Test {private Save save = new Save();public Save getSave() {return save;}public void setSave(Save save) {this.save = save;}public static void main(String[] args) {Test test = new Test();test.getSave().save();} }運行結果:
2. 使用 xml 聲明法創建對象
在 src 中創建 applicationContext.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userinfo1" class="entity.Userinfo"></bean> </beans><bean> 標簽告訴 Spring 要創建 entity 包下的 Userinfo 類的對象,放在 DI 容器里,在容器里的 id 是 userinfo1。Userinfo 如下:
package entity;public class Userinfo {public Userinfo() {System.out.println("類 Userinfo 被實例化 = " + this);} }測試類 Test:
package test;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test1 {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");} }運行結果:
如果 applicationContext.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userinfo1" class="entity.Userinfo"></bean><bean id="userinfo2" class="entity.Userinfo"></bean> </beans>如果通過 getBean(Userinfo.class) 方法獲取對象的話就會拋出 NoUniqueBeanDefinitionException 異常,因為 Spring 找到了多個對象,不知道返回哪一個。
package test;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import entity.Userinfo;public class TestNoUnique {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Userinfo userinfo = context.getBean(Userinfo.class);} }拋出以下異常 :
如何解決呢? 不要使用 getBean(Userinfo.class); , 使用 getBean(String id); 這樣就可以獲得 id 對應的唯一對象,而解決異常。
package test;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import entity.Userinfo;public class Test1_1 {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Userinfo userinfo1 = (Userinfo)context.getBean("userinfo1");Userinfo userinfo2 = (Userinfo)context.getBean("userinfo2");System.out.println(userinfo1);System.out.println(userinfo2);} }運行結果, 可以看到通過 id 獲取的對象和 Spring 創建的對象是同一個對象:
總結: getBean(Userinfo.class) 適用于只有一個 Userinfo 類實例對象的情況,而有多個 Userinfo 類對象的時候就需要使用 getBean(String id) 方法。
3. 使用 xml 和 Annotation 注解混合的方式來創建對象
使用 <context:component-scan base-package=""> 創建對象
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="entity"></context:component-scan> </beans>使用 @Component 注解,這樣 Userinfo 能被 <context:component-scan base-package="entity"> 識別并創建實例化對象。
package entity;import org.springframework.stereotype.Component;@Component public class Userinfo {public Userinfo() {System.out.println("Userinfo 構造方法執行了:" + this);} }測試類 Test 類,運行結果:
package test;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");} }getBean(Userinfo.class) 的方式運行:
package test;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import entity.Userinfo;public class Test2 {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Userinfo userinfo = (Userinfo)context.getBean(Userinfo.class);System.out.println("main run " + userinfo);} }我們也可以看到通過 id 獲取的對象和 Spring 創建的對象是同一個對象。
4. 使用全注解創建出對象
全注解配置法也稱 JavaConfig 配置法。注解 @Configuration 起著和 <beans> 標簽一樣的全局配置作用,這樣我們就不需要 xml 配置方式就能創建 JavaBean 了。而注解 @Bean 就和 <bean> 標簽的功能是一樣的,用來聲明 JavaBean。
@Bean 注解聲明創建對象的方法是名稱可以是任意的,但必須有返回值。
package tools;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import entity.Userinfo;@Configuration public class CreateBean {@Beanpublic Userinfo getUserinfo() {Userinfo userinfo1 = new Userinfo();System.out.println("創建 userinfo1 = " + userinfo1);return userinfo1;}@Beanpublic Userinfo createUserinfo() {Userinfo userinfo2 = new Userinfo();System.out.println("創建 userinfo2 = " + userinfo2);return userinfo2;} } package entity;import org.springframework.stereotype.Component;public class Userinfo {public Userinfo() {System.out.println("Userinfo 構造方法執行了:" + this);} } package test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Test4 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("tools");} }運行結果:
使用全注解發生 NoUniqueBeanDefinitionException 異常,以及解決方法
將 Test4 類的代碼加上一行代碼
package test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import entity.Userinfo;public class Test4 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("tools");Userinfo userinfo = context.getBean(Userinfo.class);} }解決辦法是給 @Bean 添加一個 name
package tools;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import entity.Userinfo;@Configuration public class CreateBean {@Bean(name = "userinfo1")public Userinfo getUserinfo() {Userinfo userinfo1 = new Userinfo();System.out.println("創建 userinfo1 = " + userinfo1);return userinfo1;}@Bean(name = "userinfo2")public Userinfo createUserinfo() {Userinfo userinfo2 = new Userinfo();System.out.println("創建 userinfo2 = " + userinfo2);return userinfo2;} }然后通過 getBean(String id) 方法獲得對象,和 xml 方式是一樣的:
package test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import entity.Userinfo;public class Test4 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("tools");Userinfo userinfo1 = (Userinfo)context.getBean("userinfo1");Userinfo userinfo2 = (Userinfo)context.getBean("userinfo2");System.out.println("main userinfo1 = " + userinfo1);System.out.println("main userinfo2 = " + userinfo2);} }運行結果:
使用 @ComponentScan 注解的 basePackages = “” 創建對象,它和 <context:component-scan base-package=""> </context:component-scan> 作用是相同的,可以進行類掃描,并且創建對象。
掃描 entity 包的類 CreateBean
package tools;import java.util.Date;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;@Configuration @ComponentScan(basePackages = "entity") public class CreateBean {@Beanpublic Date getUserinfo() {Date nowDate = new Date();System.out.println("創建 nowDate = " + nowDate);return nowDate;} } package entity;import org.springframework.stereotype.Component;@Component public class Userinfo {public Userinfo() {System.out.println("Userinfo 構造方法執行了:" + this.hashCode());} } package test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import tools.CreateBean;public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CreateBean.class);} }運行結果:
我們可以看到 entity 下的 Userinfo 類創建了一個實例對象。
使用 @ComponentScan(basePackages = "") 掃描多個包
package tools;import java.util.Date;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;@Configuration @ComponentScan(basePackages = {"entity1" , "entity2"}) public class CreateBean {@Beanpublic Date createDate() {Date nowDate = new Date();System.out.println("createDate " + nowDate.getTime());return nowDate;} } package entity1;import org.springframework.stereotype.Component;@Component public class Userinfo {public Userinfo() {System.out.println("Userinfo 構造方法執行了:" + this);} } package entity2;import org.springframework.stereotype.Repository;@Repository public class Bookinfo {public Bookinfo() {System.out.println("Bookinfo 的構造方法被調用了 " + this);} } package test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import tools.CreateBean;public class Test4 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CreateBean.class);} }運行結果:
使用 @ComponentScan(basePackageClasses = "") 掃描多個類
package tools;import java.util.Date;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;import entity1.entity2.Entity2222; import entity1.entity2.entity3.Userinfo;@Configuration //@ComponentScan(basePackageClasses = { Entity2222.class, Userinfo.class}) @ComponentScan(basePackageClasses = { Userinfo.class}) @ComponentScan(basePackageClasses = { Entity2222.class})public class CreateBean {@Beanpublic Date createDate() {Date nowDate = new Date();System.out.println("createDate " + nowDate.getTime());return nowDate;} } package entity1.entity2;import org.springframework.stereotype.Repository;@Repository public class Entity2222 {public Entity2222() {System.out.println("Entity2222 構造方法執行了:" + this.hashCode());} } package entity1.entity2.entity3;import org.springframework.stereotype.Repository;@Repository public class Bookinfo {public Bookinfo() {System.out.println("Bookinfo 的構造方法被調用了 " + this.hashCode());} } package entity1.entity2.entity3;import org.springframework.stereotype.Component;@Component public class Userinfo {public Userinfo() {System.out.println("Userinfo 構造方法執行了:" + this.hashCode());} } package test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import tools.CreateBean;public class Test4 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CreateBean.class);} }運行結果:
可以分行寫,也可以寫成一個數組
//@ComponentScan(basePackageClasses = { Entity2222.class, Userinfo.class}) @ComponentScan(basePackageClasses = { Userinfo.class}) @ComponentScan(basePackageClasses = { Entity2222.class})如果只寫 @ComponentScan, 那么掃描的將是 @Configuration 注解配置類所在包及其子包下的所有組件。
@Component 注解代表都是一個可以掃描的組件, @Repository 注解代表也是一個組件,一般代表的是 DAO 層的組件,也就是數據訪問層的組件。它們倆都可以被 @ComponentScan 組件掃描。
總結:這篇博客的例子基本來自 JavaEE 核心框架第二版。以前并沒有記錄 Spring 創建 JavaBean 的方式,所以記錄下來,方便以后學習。
代碼
轉載于:https://my.oschina.net/oldbiwang/blog/1605643
總結
以上是生活随笔為你收集整理的在 Spring中 创建 JavaBean的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#获取枚举描述代码
- 下一篇: #180111mysql启动错误