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