1. 程式人生 > >基於Spring4的Bean的裝配和依賴注入

基於Spring4的Bean的裝配和依賴注入

由於準備著手研究一下Spring BootSpring Cloud,所以抽空把Spring對Bean的裝配和Spring容器的依賴注入重新整理了一下,理解了一下內在本質!

今天主要整理的是基於註解的方式對Bean的管理,下面是具體的Demo!

Maven依賴:

<!-- Spring Context 依賴 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.3.9.RELEASE</version>
		</dependency>

		<!-- JSR 330 依賴 -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

Demo01:

//通過加入組建
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class, User.class, UserDao.class,UserService.class,UserController.class);
		//通過掃描包
		//AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.harry.**");

注: 首先獲取Spring容器applicationContext,這裡通過新增配置類組建的方式或者掃描包的方式來讓Spring對Bean進行裝配,接著通過容器才對Bean進行一系列操作。

MyConfig.Java

package com.harry.spring4.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;

/**
 * Bean的配置類,類似於applicationContext.xml裡配置的各種Bean
 * 
 * @author Harry Wan
 *
 */
@Configuration
public class MyConfig {

	/**
	 * 表示配置了一個Bean,name預設為方法名 "createMyBean"
	 * 
	 * @return
	 */
	@Bean
	@Scope(scopeName = "prototype")
	public MyBean createMyBean() {
		return new MyBean();
	}

	/**
	 * 自定義Bean的name,從容器中獲取時按定義的名稱獲取
	 * 
	 * @return
	 */
	@Bean(name = "myBean")
	@Scope(scopeName = "prototype")
	public MyBean createMyBeanWithRename() {
		return new MyBean();
	}

	@Bean
	public MyFactoryBean createMyFactoryBean() {
		return new MyFactoryBean();
	}

	@Bean
	public MyCustomFactory createMyCustomFactory() {
		return new MyCustomFactory();
	}

	@Bean
	public MyBean createMyBeanByCustomFactory(MyCustomFactory factory) {
		return factory.createMyBean();
	}

	@Bean
	public MyBean2 createMyBean2ByCustomFactory(MyCustomFactory factory) {
		return factory.createMyBean2();
	}

	@Bean
	public MyBean3 createMyBean3() {
		return new MyBean3();
	}
	
	@Bean(initMethod = "init", destroyMethod = "destroy")
	public MyBean4 createMyBean4() {
		return new MyBean4();
	}
	
	@Bean
	public MyBean5 createMyBean5() {
		return new MyBean5();
	}
	
	@Bean
	//@Primary
	public UserDao createUserDao(){
		return new UserDao();
	}
	
}

注: 這裡通過@Configuration註解表示當前為配置類,類似於專案中的applicationContext.xml,同時通過@Bean來標識自定義例項化的Bean

例項化Bean的四種方式:

第一種:

/**第一種方式: 通過自定義建立例項化Bean,交給Spring來管理**/
		//從容器中通過型別來獲取. 
		//注: 若容器中有多個例項化Bean的方法,此時通過型別來獲取,會Bean匹配錯誤
		//System.out.println(applicationContext.getBean(MyBean.class));
		
		//從容器中通過名稱來獲取
		System.out.println(applicationContext.getBean("createMyBean"));
		System.out.println(applicationContext.getBean("myBean"));

配置:

/**
	 * 表示配置了一個Bean,name預設為方法名 "createMyBean"
	 * 
	 * @return
	 */
	@Bean
	@Scope(scopeName = "prototype")
	public MyBean createMyBean() {
		return new MyBean();
	}

	/**
	 * 自定義Bean的name,從容器中獲取時按定義的名稱獲取
	 * 
	 * @return
	 */
	@Bean(name = "myBean")
	@Scope(scopeName = "prototype")
	public MyBean createMyBeanWithRename() {
		return new MyBean();
	}


注:在配置類中自定義例項化Bean方法,並且使用@Bean註解標識,交給Spring管理,最後通過容器獲取Bean例項.在通過型別獲取時,如果在容器中有多個例項化Bean的方法,Spring會報匹配錯誤,在通過名稱獲取時,如果不自定義@Bean(name = "myBean"),預設的名稱為例項化Bean的方法名applicationContext.getBean("createMyBean")

第二種:

/** 第二種方式: 通過BeanFactory來建立例項化Bean**/
		//通過型別獲取FactoryBean建立的Bean的例項物件
		//System.out.println(applicationContext.getBean(MyBean2.class));
		//通過名字來獲取FactoryBean建立的Bean的例項物件
		System.out.println(applicationContext.getBean("createMyFactoryBean"));
		
		//通過型別獲取到的是MyFactoryBean本身,並非MyFactoryBean創建出來的Bean
		System.out.println(applicationContext.getBean(MyFactoryBean.class));
		//通過名稱獲取到的是MyFactoryBean本身,並非MyFactoryBean創建出來的Bean
		System.out.println(applicationContext.getBean("&createMyFactoryBean"));

MyFactoryBean.java
package com.harry.spring4.demo;

import org.springframework.beans.factory.FactoryBean;
/**
 * 通過FactoryBean 來建立物件
 * @author Harry Wan
 *
 */
public class MyFactoryBean implements FactoryBean<MyBean2> {
	
	//獲取到FactoryBean所建立的實力物件
	public MyBean2 getObject() throws Exception {
		return new MyBean2();
	}
	
	//獲取Bean的型別
	public Class<?> getObjectType() {
		return MyBean2.class;
	}

	public boolean isSingleton() {
		return true;
	}

}


注:這裡通過實現FactoryBean介面傳入需要例項化的Bean型別,實現對應的方法,再將我們自定義的MyFactoryBean新增到配置類中,最終來獲取我們需要例項化的Bean物件。 由於FactoryBean也可以抽象成Bean的一種,所以在獲取時要區分我們需要的目標Bean物件和FactoryBean物件

第三種:

/** 第三種方式: 通過自定義Factory來建立Bean例項,把自定義的Factory也當作Bean交給Spring來管理 **/
		//可以通過型別來獲取MyBean.class,為了避免通過型別匹配到多個例項化Bean的方法,改為通過Name來獲取
		System.out.println(applicationContext.getBean("createMyBeanByCustomFactory"));
		System.out.println(applicationContext.getBean("createMyBean2ByCustomFactory"));

自定義例項化Bean的工廠類MyCustomFactory.java:

package com.harry.spring4.demo;

public class MyCustomFactory {
	
	public MyBean createMyBean() {
		return new MyBean();
	}
	
	public MyBean2 createMyBean2() {
		return new MyBean2();
	}
}


配置類MyConfig.java:

@Bean
	public MyCustomFactory createMyCustomFactory() {
		return new MyCustomFactory();
	}

	@Bean
	public MyBean createMyBeanByCustomFactory(MyCustomFactory factory) {
		return factory.createMyBean();
	}

	@Bean
	public MyBean2 createMyBean2ByCustomFactory(MyCustomFactory factory) {
		return factory.createMyBean2();
	}

注: 這裡將自定義Bean的工廠類加入到Spring容器中進行管理,在例項化目標Bean時,對於需要的工廠類引數,Spring會自動去匹配當前容器中已經裝配好的對應工廠物件進行傳入

第四種:

/**第四種方式: 通過使用@Component元件相關注解,交給Spring容器裝配**/
		//注: 實際開發中通常使用scan掃描包自動加入Spring容器(new AnnotationConfigApplicationContext("com.harry.**");),如若其他方式要手動加入到Spring容器中
		System.out.println(applicationContext.getBeansOfType(User.class));//獲取Spring容器管理Bean時該Bean使用的預設名稱(Map: 名稱 = 例項化物件)
		//@Component
		System.out.println(applicationContext.getBean(User.class));
		System.out.println(applicationContext.getBean("myUser"));
		//@Repository
		System.out.println(applicationContext.getBean(UserDao.class));
		//@Service
		System.out.println(applicationContext.getBean(UserService.class));
		//@Controller
		System.out.println(applicationContext.getBean(UserController.class));
注:通過使用@Component等註解表示當前類為Spring的組建,Spring預設進行裝配進行管理,這也是實際開發中用的最多的方式 //---------------------------------------------------------這是一道華麗的分界線------------------------------------------------------

實現Bean在被Spring容器載入之後和被銷燬之後自定義新增業務邏輯的三種方式

第一種:

/**第一種方式: 目標Bean實現InitializingBean, DisposableBean介面,實現對應的afterPropertiesSet()和destroy()方法**/
		System.out.println(applicationContext.getBean("createMyBean3"));

package com.harry.spring4.demo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class MyBean3 implements InitializingBean, DisposableBean {
	
	/**
	 * 當Bean被Spring載入之後會執行
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("==It will be executed after being Loaded==");
	}
	
	/**
	 * 當Bean銷燬之後會執行
	 */
	@Override
	public void destroy() throws Exception {
		System.out.println("==It will be executed after being Destroyed==");
	}
}

注:目標Bean通過實現InitializingBean, DisposableBean介面,實現對應的afterPropertiesSet()和destroy()方法

第二種

/**第二種方式: 在註解@Bean是指定(initMethod = "init", destroyMethod = "destroy")**/
		System.out.println(applicationContext.getBean("createMyBean4"));
配置類:
@Bean(initMethod = "init", destroyMethod = "destroy")
	public MyBean4 createMyBean4() {
		return new MyBean4();
	}

目標Bean:
package com.harry.spring4.demo;

public class MyBean4 {
	/**
	 * 當Bean被Spring載入之後會執行
	 */
	public void init() {
		System.out.println("==It will be executed after being Loaded==");
	}
	
	/**
	 * 當Bean銷燬之後會執行
	 */
	public void destroy(){
		System.out.println("==It will be executed after being Destroyed==");
	}
}


注:這裡通過在配置類註解@Bean中標註initMethod , destroyMethod方法來實現,這也是實際開發中最常用的方式,基於Spring提供的@Bean註解的配置

第三種

/**第三種方式: 通過Javax(JSR-250)註解@PostConstruct和@PreDestroy方式**/
		System.out.println(applicationContext.getBean("createMyBean5"));
目標Bean:
package com.harry.spring4.demo;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class MyBean5 {
	/**
	 * 當Bean被Spring載入之後會執行
	 */
	@PostConstruct
	public void init() {
		System.out.println("==It will be executed after being Loaded==");
	}
	
	/**
	 * 當Bean銷燬之後會執行
	 */
	@PreDestroy
	public void destroy(){
		System.out.println("==It will be executed after being Destroyed==");
	}
}



注:通過使用Javax註解@PostConstruct和@PreDestroy實現 //---------------------------------------這是一道華麗的分界線----------------------------------------------------

注入容器的三種方式

package com.harry.spring4.demo;

import javax.annotation.Resource;
import javax.inject.Inject;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Repository;
/**
 * Spring 依賴注入 
 * @author Harry Wan
 *
 */
public class MyDemo2 {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.harry.**");
		
		//使用@Repository註解裝配
		System.out.println(applicationContext.getBean("userDao"));
		//使用@Bean 自定義例項化物件裝配
		System.out.println(applicationContext.getBean("createUserDao"));
		
				/**注入的三種方式**/
		//@Autowired 依賴 UserDao    ---Spring提供的注入方式,可以指定具體裝配哪一個
		//@Resource 依賴User		   ----JSR-250提供的注入方式(JDK自帶)
		//@Inject 依賴MyBean		   ----JSR-330提供的注入方式(需要新增依賴)
		UserService userService = applicationContext.getBean(UserService.class);
		
		//在有多個例項化Bean的情況下,預設情況下,Spring優先會注入@Repository註解的組建Bean,
		//可以在@Autowired下使用@Qualifier(value = "createUserDao")或者在@Bean下使用@Primary來指定裝配哪一個
		System.out.println(userService);
		
		applicationContext.close();
	}
}


package com.harry.spring4.demo;

import javax.annotation.Resource;
import javax.inject.Inject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserService {
	@Autowired
	@Qualifier(value="createUserDao")
	private UserDao userDao;
	
	//JSR-250提供的注入方式(JDK自帶)
	@Resource
	private User user;
	
	//JSR-330提供的注入方式(需要新增依賴)
	@Inject
	private MyBean myBean;

	@Override
	public String toString() {
		return "UserService [userDao=" + userDao + ", user=" + user + ", myBean=" + myBean + "]";
	}
	
	
	
}

@Bean
	//@Primary
	public UserDao createUserDao(){
		return new UserDao();
	}


注:第一種方式: 最常用的方法,使用Spring提供的@Autowired註解,當容器中有多個依賴注入的Bean物件時,可以使用 @Qualifier(value = "createUserDao")或者在@Bean下使用@Primary來指定裝配哪一個        第二種方式:使用JSR-250提供的注入方式(JDK自帶),基於註解@Resource依賴注入        第三種方式:使用JSR-330提供的注入方式(需要新增依賴), 基於註解@Inject實現依賴注入 //-------------------------------這是一道華麗的分界線----------------------------------------------------

基於註解設定在Spring掃描包時自動忽略相應Bean的裝配:

package com.harry.spring4.demo;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.stereotype.Service;

public class MyDemo3 {
	public static void main(String[] args) {
		/**
		 * 把掃描包的註解配置資訊新增在AnnotationScanConfig中,通過Spring容器讀取配置檔案的方式載入掃描配置
		 * @ComponentScan(basePackages="com.harry.**",[email protected](type=FilterType.ASSIGNABLE_TYPE,classes={UserService.class,MyConfig.class}))
		 * 排除用@Service註解的UserService和在MyConfig中自定義配置的Bean的掃描
		 * 
		 * 如若使用@Component註解註釋的Bean,可直接排除
		 * 如若使用Config配置檔案自定義例項化Bean的方式,不能直接排除Bean的本身,要填寫Config配置類,從而來排除配置檔案中配置的Bean
		 * 
		 */
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationScanConfig.class);
		System.out.println(applicationContext.getBean(User.class));
		System.out.println(applicationContext.getBean(UserService.class));
		System.out.println(applicationContext.getBean(MyBean.class));
		applicationContext.close();
	}
}


掃描配置AnnotationScanConfig.java
package com.harry.spring4.demo;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

@Configuration
@ComponentScan(basePackages="com.harry.**",[email protected](type=FilterType.ASSIGNABLE_TYPE,classes={UserService.class,MyConfig.class}))
public class AnnotationScanConfig {

}


注: 使用@Configuration表示當前為以配置類加入到Spring容器中, @ComponentScan表示Spring掃描的配置資訊,通過指定excludeFilters來過濾相應Bean的裝配,FilterType.ASSIGNABLE_TYPE表示我們傳入指定的要忽略的目標Bean的型別或者Bean所在的配置類。      如果Bean使用的是@Component等註解標識,可以直接在Filter中指定該Bean的型別,從而忽略裝配      如果Bean使用的是配置類的方式,在配置類中使用@Bean的註解自定義例項化Bean,我們需要將配置類加到Filter中,從而對該Bean進行忽略,若加Bean本身,而非其Bean所在的配置類,則達不到忽略的效果

最後,由於Bean都是預設以單例的形式裝配在Spring容器中,我們可以通過@Scope(scopeName = "prototype")來標識,表示每次從容器中獲取該Bean是都是重新例項化一個新的物件。

Demo執行示例:

相關推薦

基於Spring4的Bean的裝配依賴注入

由於準備著手研究一下Spring Boot 和Spring Cloud,所以抽空把Spring對Bean的裝配和Spring容器的依賴注入重新整理了一下,理解了一下內在本質! 今天主要整理的是基於註

在IoC容器中裝配Bean之-----------基於XML的配置(依賴注入)

一.Spring裝配Bean的簡要概述 1.要使應用程式中的Spring容器成功啟動, 需要同時具備以下三個方面的條件: (1)Spring框架的類包都已經被Maven專案依賴成功. (2)應用程式為Spring提供了完整的Bean配置資訊. (3)Bean的類都已經

六、基於xml的bean例項化依賴注入

例項化bean bean 定義基本上就是用來建立一個或多個物件的配置,當需要一個 bean 的時候,容器檢視配置並且根據 bean 定義封裝的配置元資料建立(或獲取)一個實際的物件。 如果您想要配置的一個bean定義static巢狀類,你必須使用二進位

淺談Angular6的服務依賴注入

在開發中,元件一般用來寫檢視有關的功能,服務則寫一些其他的邏輯,諸如從伺服器獲取資料、驗證使用者輸入或直接往控制檯中寫日誌等工作. 先解釋兩個概念: Providers(提供商):是個比較抽象的名詞,我們把它想象為'圖紙'更好理解一些,就比如我們想要生產汽車,就需要先有汽車的圖紙,圖紙

Spring 基於 XML 的 IOC依賴注入的 細節[掌握哦!!!

Spring之 IOC的繼續—bean標籤 --依賴注入 DI— 02 BeanFactory 和 ApplicationContext 的區別 BeanFactory 才是 Spring 容器中的頂層介面。ApplicationContext 是它的子介面。BeanFactory 和

Spring學習--IOC基礎 知道什麼叫做控制反轉依賴注入

IOC,中文的意思的‘控制反轉’,它是一種設計思想,真正的含義是將設計好的物件交給Spring容器控制,而不是像以往的在物件的內部直接控制。 誰控制誰?控制什麼? IOC容器控制物件;控制什麼?控制外部資源的獲取(物件和檔案等) 為什麼是反轉,哪些方面反轉了?所謂反轉是由容器來幫忙建立及

控制反轉 依賴注入

控制反轉程式設計思想的定義 控制反轉就是我們經常聽所的英文縮寫 IoC,英文全名是 Inverse of Controller 1. 控制反轉不是一種技術,而是一種軟體開發中比較先進的程式設計思想 說道先進,那麼我們先聊聊比較落後的程式設計思想吧。

Spring的控制反轉IOC依賴注入DI

首先想說說IoC(Inversion of Control,控制反轉)。這是spring的核心,貫穿始終。所謂IoC,對於spring框架來說,就是由spring來負責控制物件的生命週期和物件間的關係: 誰控制誰,控制什麼:傳統Java SE程式設計,我們直接在物件內部通過new進行

控制反轉(IoC)依賴注入(DI)

容器,字面上理解就是裝東西的東西。常見的變數、物件屬性等都可以算是容器。一個容器能夠裝什麼,全部取決於你對該容器的定義。當然,有這樣一種容器,它存放的不是文字、數值,而是物件、物件的描述(類、介面)或者是提供物件的回撥,通過這種容器,我們得以實現許多高階的功能,其中最常提到的,就是 “解耦” 、“依

複習之spring基礎(一)——控制反轉(ioc)依賴注入(di)

Spring的核心——控制反轉 ioc: 反轉控制. 建立物件的方式反轉了.從我們自己建立物件,反轉給spring(程式)來建立. 實現ioc思想需要,di做支援 di: 依賴注入.將必須的屬性注入到物件當中.是實現ioc思想必須條件. 三種物件建立方式 無參

laravel 資料模型依賴注入,輕鬆刪除1對多記錄

laravel是PHP框架,以下操作似乎沒有用到PHP和MYSQL語句,就這麼優雅地搞定了: 有兩個表: 賽事表:races 賽事專案表:items (包含欄位:race_id) 一個賽事有多個比賽專案,多個比賽專案對應一個賽事。 建立模型: Race.php <?php

深入理解spring容器中的控制反轉(IOC)依賴注入(DI)

首先在開篇之前我們一定一定要明確的就是:DI和IOC並不是兩個概念,DI是IOC思想在應用上的具體例子。 什麼是控制反轉(IOC)? “控制”就是指一件事物對另一件事物進行一種管理,而另一件事物處在一件事物的管理之下,這就叫控制。 在面向物件程式設計的時候,每一個程式的

【轉】spring中對控制反轉依賴注入的理解

由於最近沒有太多時間,不能深入的瞭解控制反轉和依賴注入,只好把別人的理解轉載過來,非常痛恨市面上各種教程對所謂的術語張口就來,等自己有了時間一定要寫出新手都能看懂的教程。     首先想說說IoC(Inversion of Control,控制反轉)。這是spring的核心,貫穿始終。所謂IoC

spring(一)控制反轉依賴注入

       控制反轉降低了類和類之間的耦合度,利於修改和擴充套件,提供了完整的IOC實現,讓我們專注於業務類和Dao類的設計,體現的是面向介面程式設計的思想,核心是BeanFactory。 需要引入的架包: commons-logging: spring執行依賴這個元件

SpringMVC學習指南【筆記1】建立bean例項的方法依賴注入

Spring MVC 主要從Spring框架、Servlet、JSP這3個方面來講。   Java企業版技術包括JMS、EJB、JSF、JPA。   Java企業版容器:GlassFish、JBoss、Oracle、Weblogic、IBM WebSphere   T

【Scala】Cake模式依賴注入

依賴注入(Dependency Injection)和控制反轉(Inversion of Control) Dependency Injection & Inversion of Control是Martin Fowler在2004年所提出來的一個概念

Spring學習(1):控制反轉(IoC)依賴注入(DI)的詳解以及註解(annotation)開發入門案例

前言 以往的java學習中,我們要想得到一個物件,就把它new出來。如:Apple apple = new Apple(); 在一些複雜的系統中,一個物件A可能依賴於物件B,C等(程式碼表現為A類持有B,C類的物件作為A類的屬性)。以往來說,我們想要使用B,

Spring Boot學習一之Spring Beans依賴注入

  你可以自由地使用任何標準的Spring框架技術去定義beans和它們注入的依賴。簡單起見,我們經常使用 @ComponentScan 註解搜尋beans,並結合 @Autowired 構造器注入。   如果遵循以上的建議組織程式碼結構(將應用的main類放到包的最上層,即rootpackage),那麼你

關於laravel 自動載入依賴注入、服務容器、服務提供者的理解--1

class Container {     protected $binds;      protected $instances;     public function bind($abstract, $concrete)     {         if ($concrete instanceof C

Spring Boot自動配置(Auto-Configuration),@EnableAutoConfiguration,Spring Beans依賴注入

自動配置(Auto-Configuration) 自動配置(auto-configuration)是Spring Boot最重要的特性之一,因為該特性會根據應用的classpath(這個主要是根據maven pom.xml決定),annotations和其他的