- Set注入
- package com.bless.springdemo.action;
- public class SpringAction {
- //注入對象springDao
- private SpringDao springDao;
- //一定要寫被注入對象的set方法
- public void setSpringDao(SpringDao springDao) {
- this.springDao = springDao;
- }
- public void ok(){
- springDao.ok();
- }
- }
- <!--配置bean,配置后該類由spring管理-->
- <bean name="springAction" class="com.bless.springdemo.action.SpringAction">
- <!--(1)依賴注入,配置當前類中相應的屬性-->
- <property name="springDao" ref="springDao"></property>
- </bean>
- <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
- 構造器注入
- public class SpringAction {
- //注入對象springDao
- private SpringDao springDao;
- private User user;
- public SpringAction(SpringDao springDao,User user){
- this.springDao = springDao;
- this.user = user;
- System.out.println("構造方法調用springDao和user");
- }
- public void save(){
- user.setName("卡卡");
- springDao.save(user);
- }
- }
- <!--配置bean,配置后該類由spring管理-->
- <bean name="springAction" class="com.bless.springdemo.action.SpringAction">
- <!--(2)創建構造器注入,如果主類有帶參的構造方法則需添加此配置-->
- <constructor-arg ref="springDao"></constructor-arg>
- <constructor-arg ref="user"></constructor-arg>
- </bean>
- <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
- <bean name="user" class="com.bless.springdemo.vo.User"></bean>
- <bean name="springAction" class="com.bless.springdemo.action.SpringAction">
- <constructor-arg index="0" ref="springDao"></constructor-arg>
- <constructor-arg index="1" ref="user"></constructor-arg>
- </bean>
- <constructor-arg type="java.lang.String" ref=""/>
- 靜態工廠的方法注入
- package com.bless.springdemo.factory;
- import com.bless.springdemo.dao.FactoryDao;
- import com.bless.springdemo.dao.impl.FactoryDaoImpl;
- import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl;
- public class DaoFactory {
- //靜態工廠
- public static final FactoryDao getStaticFactoryDaoImpl(){
- return new StaticFacotryDaoImpl();
- }
- }
- public class SpringAction {
- //注入對象
- private FactoryDao staticFactoryDao;
- public void staticFactoryOk(){
- staticFactoryDao.saveFactory();
- }
- //注入對象的set方法
- public void setStaticFactoryDao(FactoryDao staticFactoryDao) {
- this.staticFactoryDao = staticFactoryDao;
- }
- }
- <!--配置bean,配置后該類由spring管理-->
- <bean name="springAction" class="com.bless.springdemo.action.SpringAction" >
- <!--(3)使用靜態工廠的方法注入對象,對應下面的配置文件(3)-->
- <property name="staticFactoryDao" ref="staticFactoryDao"></property>
- </property>
- </bean>
- <!--(3)此處獲取對象的方式是從工廠類中獲取靜態方法-->
- <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>
- 實例工廠的方法注入
- public class DaoFactory {
- //實例工廠
- public FactoryDao getFactoryDaoImpl(){
- return new FactoryDaoImpl();
- }
- }
- public class SpringAction {
- //注入對象
- private FactoryDao factoryDao;
- public void factoryOk(){
- factoryDao.saveFactory();
- }
- public void setFactoryDao(FactoryDao factoryDao) {
- this.factoryDao = factoryDao;
- }
- }
- <!--配置bean,配置后該類由spring管理-->
- <bean name="springAction" class="com.bless.springdemo.action.SpringAction">
- <!--(4)使用實例工廠的方法注入對象,對應下面的配置文件(4)-->
- <property name="factoryDao" ref="factoryDao"></property>
- </bean>
- <!--(4)此處獲取對象的方式是從工廠類中獲取實例方法-->
- <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>
- <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>
- 總結
- <bean name="..." class="..." scope="prototype">
- Spring的依賴注入(接口注入)
- 2009-11-26 10:06 148人閱讀 評論(0) 收藏 舉報
- 這篇文章來談談《Spring Framework 開發參考手冊》的3.3.3.1小節中的Lookup方法注入。
- 仔細看看文檔,這種方法主要是用在Singleton的Object中使用非Singleton的Bean時,通過lookup-method的
- 那個方法來取得非Singleton的Bean。一般用的不多,在用這種定義之前最好想明白你的需求。
- · 先建立一個包:javamxj.spring.basic.lookup ,然后把以下5個文件放在這個包下。
- Hello.java.
- package javamxj.spring.basic.lookup;
- public interface Hello {
- public Random getRandom();
- public abstract Random createRandom();
- }
- Random.java
- package javamxj.spring.basic.lookup;
- public class Random {
- private int i = (int) (100 * Math.random());
- public void printRandom() {
- System.out.println("輸出隨機整數: " + i);
- }
- }
- HelloAbstract.java
- package javamxj.spring.basic.lookup;
- public abstract class HelloAbstract implements Hello {
- private Random random;
- public Random getRandom() {
- return random;
- }
- public void setRandom(Random random) {
- this.random = random;
- }
- public abstract Random createRandom();
- }
- beans.xml
- <?xml version="1.0" encoding="GBK"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <bean id="ran" class="javamxj.spring.basic.lookup.Random" singleton="false"/>
- <bean id="hello" class="javamxj.spring.basic.lookup.HelloAbstract">
- <lookup-method name="createRandom" bean="ran"/>
- <property name="random">
- <ref local="ran"/>
- </property>
- </bean>
- </beans>
- Main.java
- package javamxj.spring.basic.lookup;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.xml.XmlBeanFactory;
- import org.springframework.core.io.ClassPathResource;
- import org.springframework.core.io.Resource;
- public class Main {
- public static void main(String[] args) {
- Resource res = new ClassPathResource( "javamxj/spring/basic/lookup/beans.xml");
- BeanFactory ft = new XmlBeanFactory(res);
- Hello h = (Hello) ft.getBean("hello");
- Random r1 = h.getRandom();
- Random r2 = h.getRandom();
- System.out.println("沒有采用Lookup方法注入:");
- System.out.println("Random 的兩個實例指向同一個引用:" + (r1 == r2));
- r1.printRandom();
- r2.printRandom();
- Random r3 = h.createRandom();
- Random r4 = h.createRandom();
- System.out.println("/n采用Lookup方法注入:");
- System.out.println("Random 的兩個實例指向同一個引用:" + (r3 == r4));
- r3.printRandom();
- r4.printRandom();
- }
- }
- 簡單說明一下:
- · Hello是一個接口類,實現面向接口編程。
- · Random類用來輸出隨機整數。
- · HelloAbstract是一個抽象類,包含了一個屬性:random,還包含一個抽象方法createRandom(),如果這個方法不是抽象的,spring會重寫已有的實現。
- · beans.xml中定義了兩個bean,ran指向Rondom類,注意它不是singleton的;hello指向HelloAbstract類,其中的random屬性指向ran,createRandom方法也指向ran。
- · 在Main類中,Hello類分別利用getRandom()和createRandom()方法來調用Random類。
- · 這次需要將 spring-framework主目錄/lib/cglib 目錄中的cglib-nodep-2.1_2.jar加入到項目的 Libraries中,使用其中的動態代理。
- 運行結果:
- 沒有采用Lookup方法注入:
- Random 的兩個實例指向同一個引用:true
- 輸出隨機整數: 98
- 輸出隨機整數: 98
- 采用Lookup方法注入:
- Random 的兩個實例指向同一個引用:false
- 輸出隨機整數: 51
- 輸出隨機整數: 26
- 本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/javamxj/archive/2005/08/17/456600.aspx
我的理解:接口注入其實是,通過配置Spring的lookup-method,及返回值 ,可以返回接口中方法的返回值而不需要實現接口中的抽象方法
注解注入顧名思義就是通過注解來實現注入,Spring和注入相關的常見注解有Autowired、Resource、Qualifier、Service、Controller、Repository、Component。
- Autowired是自動注入,自動從spring的上下文找到合適的bean來注入
- Resource用來指定名稱注入
- Qualifier和Autowired配合使用,指定bean的名稱
- Service,Controller,Repository分別標記類是Service層類,Controller層類,數據存儲層的類,spring掃描注解配置時,會標記這些類要生成bean。
- Component是一種泛指,標記類是組件,spring掃描注解配置時,會標記這些類要生成bean。
上面的Autowired和Resource是用來修飾字段,構造函數,或者設置方法,並做注入的。而Service,Controller,Repository,Component則是用來修飾類,標記這些類要生成bean。
下面我們通過實例項目來看下spring注解注入的使用。
首先新建一個maven項目,並在pom中添加spring相關的依賴,如果不知道添加那些依賴,請參照上一篇文章。
然后新建CarDao類,給它添加@Repository注解,如下代碼:
package cn.outofmemory.helloannotation; import org.springframework.stereotype.Repository; @Repository public class CarDao { public void insertCar(String car) { String insertMsg = String.format("inserting car %s", car); System.out.println(insertMsg); } }
新建CarService類,並給該類標注@Service注解,在這個類中定義CarDao的字段,並通過Autowired來修飾此字段,這樣上面定義的CarDao類的實例就會自動注入到CarService的實例中了。
package cn.outofmemory.helloannotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class CarService { @Autowired private CarDao carDao; public void addCar(String car) { this.carDao.insertCar(car); } }
注意:Autowired注解有一個可以為空的屬性required,可以用來指定字段是否是必須的,如果是必需的,則在找不到合適的實例注入時會拋出異常。
下面我們在App.java中使用上面測試下注解注入:
package cn.outofmemory.helloannotation; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { ApplicationContext appContext = new AnnotationConfigApplicationContext("cn.outofmemory.helloannotation"); CarService service = appContext.getBean(CarService.class); service.addCar("寶馬"); } }
在上面的main方法中首先我們初始化了appContext,他是AnnotationConfigApplicationContext,它的構造函數接受一個package的名稱,來限定要掃描的package。然后就可以通過appContext的getBean方法獲得CarService的實例了。
上面的例子非常簡單,單純的使用AnnotationConfigApplicationContext就可以了,但是在實際項目中情況往往沒有這么簡單,還是需要spring配置文件的。在spring配置文件中也可以通過下面的配置讓spring自動掃描注解配置。
<!-- bean annotation driven --> <context:annotation-config /> <context:component-scan base-package="cn.outofmemory.helloannotation" > </context:component-scan>
下面我們看下混合使用spring配置和注解的例子,首先在項目中添加source folder,src/main/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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!-- bean annotation driven --> <context:annotation-config /> <context:component-scan base-package="cn.outofmemory.helloannotation" > </context:component-scan> <bean id="sqliteCarDao" class="cn.outofmemory.helloannotation.CarDao" > <constructor-arg name="driver" value="sqlite"/> </bean> </beans>
在上面的配置文件中,我們通過context:annotation-config和context:component-sacn節點來指定要掃描注解注入,然后又定義了一個id為sqliteCarDao的bean,它的構造函數的driver值為sqlite。
我們修改下App.java使用xml配置文件,再運行下App看下會怎樣。
package cn.outofmemory.helloannotation; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { //ApplicationContext appContext = new AnnotationConfigApplicationContext("cn.outofmemory.helloannotation"); ApplicationContext appContext = new ClassPathXmlApplicationContext("/spring.xml"); CarService service = appContext.getBean(CarService.class); service.addCar("寶馬"); } }
運行程序發現輸出為:inserting car 寶馬 into mysql
,顯然CarService自動注入的CarDao使用了默認構造函數構造的實例。是否可以通過注解指定使用spring.xml中配置的sqliteCarDao呢?
我們可以修改下CarService類,通過Qualifier注解來指定要使用的bean的名字。
如下,在指定Autowired注解時,同時指定Qualifier注解指定bean的名字
@Autowired @Qualifier("sqliteCarDao") private CarDao carDao;
重新運行下App.java 這次輸出的是inserting car 寶馬 into sqlite
,這次使用了spring.xml中配置的bean了。
在文中開頭我們還提到了Resouce注解,這個注解可以指定名字注入,我們再次修改下CarService類:
@Resource(name="sqliteCarDao") private CarDao carDao;
javax.annotation.Resource注解實現的效果和@Autowired+@Qualifier的效果是一樣的。