基於Spring4的Bean的裝配和依賴注入
由於準備著手研究一下Spring Boot 和Spring 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和其他的