[spring]從頭開始-Inject
開發工具:IntelliJ IDEA 13
開發環境:jdk1.6.0_45
Framework:spring 3
注入有幾種方式:
【第一種】
就是單純使用 xml 來配置
範例如下:
InjectSimple.java
package com.test;
import org.springframework.context.support.GenericXmlApplicationContext;
/**
* Created by Hsu on 2014/7/10.
*/
public class InjectSimple {
private String name;
private int age;
private float height;
private boolean programmer;
private Long ageInSeconds;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public boolean isProgrammer() {
return programmer;
}
public void setProgrammer(boolean programmer) {
this.programmer = programmer;
}
public Long getAgeInSeconds() {
return ageInSeconds;
}
public void setAgeInSeconds(Long ageInSeconds) {
this.ageInSeconds = ageInSeconds;
}
public String toString(){
return "Name :" + name + "\n"
+ "Age:" + age + "\n"
+ "Age in Seconds: " + ageInSeconds + "\n"
+ "Height: " + height + "\n"
+ "Is Programmer?: " + programmer;
}
public static void main(String[] args) {
//使用ApplicationContext 的衍伸類別 存取 xml 檔
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("resource/spring-config.xml");
ctx.refresh();
InjectSimple simple = (InjectSimple)ctx.getBean("injectSimple");
System.out.println(simple);
}
}
上方標示紅色的部分就表示要 spring 自動 Inject 的部分 至少需要設定 setter
搭配 resource/spring-config.xml
見文生意,此為spring 使用的設定檔,可任意取名,但使用時須引入 相關必要的標頭
如下:
<?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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd">
any context….
</beans>
下面解釋一下當中一些重要常用標籤的意思
context: The contextnamespace provides support for configuring Spring’s ApplicationContext.
p: The pnamespace provides a simpler DI configuration for Setter Injection.
c: New in Spring 3.1, the cnamespace provides a more simple DI configuration for Constructor Injection.
util: The utilnamespace provides some usefulutilities for DI configuration.
Spring also provides a lot of namespace for various purpose, such as aopfor AOP support, tx for
transaction support
//Spring XML Configuration with Annotation Support
// Namespace declarations skipped
//若有使用到 Annotation 則需加入下面第一行的配置
//第二行指的是 搭配 Autowire 時,指定spring要自動配置的文件落在哪個 package
<context:annotation-config/>
<context:component-scan base-package="com.test.annotation" />
範例如下:
spring-config.xml
..
..標頭的部分省略
<bean id="injectSimple" class="com.test.InjectSimple">
<property name="name">
<value>John Smith</value>
</property>
<property name="age">
<value>35</value>
</property>
<property name="height">
<value>1.78</value>
</property>
<property name="programmer">
<value>true</value>
</property>
<property name="ageInSeconds">
<value>1103760000</value>
</property>
</bean>
..結尾省略
由上可以看到,要Inject的property 都指定好了 name,相對應於要注入的 field name,
其中 value 支援 java int/float/double/boolean/string 的自動轉換
範例的執行結果為:
Name :John Smith
Age:35
Age in Seconds: 1103760000
Height: 1.78
Is Programmer?: true
【第二種】
在XML當中也支援 SpEL(The Spring Expression Language) 取值
範例如下:
InjectSimpleConfig.java
package com.test;
/**
* Created by Hsu on 2014/7/10.
*/
public class InjectSimpleConfig {
//準備要拿來取值的field
private String name = "John Smith";
private int age = 35;
private float height = 1.78f;
private boolean programmer = true;
private Long ageInSeconds = 1103760000L;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public boolean isProgrammer() {
return programmer;
}
public void setProgrammer(boolean programmer) {
this.programmer = programmer;
}
public Long getAgeInSeconds() {
return ageInSeconds;
}
public void setAgeInSeconds(Long ageInSeconds) {
this.ageInSeconds = ageInSeconds;
}
}
InjectSimpleSpel.java
package com.test;
import org.springframework.context.support.GenericXmlApplicationContext;
/**
* Created by Hsu on 2014/7/10.
*/
public class InjectSimpleSpel {
private String name;
private int age;
private float height;
private boolean programmer;
private Long ageInSeconds;
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("resource/spring-config.xml");
ctx.refresh();
InjectSimpleSpel simple = (InjectSimpleSpel)ctx.getBean("injectSimpleSpel");
System.out.println(simple);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public boolean isProgrammer() {
return programmer;
}
public void setProgrammer(boolean programmer) {
this.programmer = programmer;
}
public Long getAgeInSeconds() {
return ageInSeconds;
}
public void setAgeInSeconds(Long ageInSeconds) {
this.ageInSeconds = ageInSeconds;
}
@Override
public String toString(){
return "Name :" + name + "\n"
+ "Age:" + age + "\n"
+ "Age in Seconds: " + ageInSeconds + "\n"
+ "Height: " + height + "\n"
+ "Is Programmer?: " + programmer;
}
}
單單看這兩個檔案應該是看不出的所以然,要搭配 spring-config.xml 服用才看得出效果
範例如下:
spring-config.xml
..
..標頭的部分省略
<bean id="injectSimpleConfig" class="com.test.InjectSimpleConfig" />
<bean id="injectSimpleSpel" class="com.test.InjectSimpleSpel">
<property name="name" value="#{injectSimpleConfig.name}" />
<property name="age" value="#{injectSimpleConfig.age+1}" />
<property name="height" value="#{injectSimpleConfig.height}" />
<property name="programmer" value="#{injectSimpleConfig.programmer}" />
<property name="ageInSeconds" value="#{injectSimpleConfig.ageInSeconds}" />
</bean>
..結尾省略
注意到上段標示紅色的部分,使用的就是SpEL,與其他 bean 之間的關系用顏色標註出來
執行結果
Name :John Smith
Age:36
Age in Seconds: 1103760000
Height: 1.78
Is Programmer?: true
Age 加 1 了喔,表示 SpEL 當中還可以加入一些operator 是沒問題
【第三種】
還有另一種Inject 是使用 Annotation,也就是使用標註的部分來設定,不透過 xml 檔案
使用範例:
InjectSimpleAnotation.java
package com.test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.stereotype.Service;
/**
* Created by Hsu on 2014/7/10.
*/
//宣告該class 為一 spring 用的 service,並指定名稱
@Service("InjectSimpleAnotation")
public class InjectSimpleAnotation {
//使用Value 來注入值
@Value("John Smith")
private String name;
@Value("37")
private int age;
@Value("1.78")
private float height;
@Value("true")
private boolean programmer;
@Value("1103760000")
private Long ageInSeconds;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public boolean isProgrammer() {
return programmer;
}
public void setProgrammer(boolean programmer) {
this.programmer = programmer;
}
public Long getAgeInSeconds() {
return ageInSeconds;
}
public void setAgeInSeconds(Long ageInSeconds) {
this.ageInSeconds = ageInSeconds;
}
public String toString(){
return "Name :" + name + "\n"
+ "Age:" + age + "\n"
+ "Age in Seconds: " + ageInSeconds + "\n"
+ "Height: " + height + "\n"
+ "Is Programmer?: " + programmer;
}
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("resource/spring-config.xml");
ctx.refresh();
InjectSimpleAnotation simple = (InjectSimpleAnotation)ctx.getBean("InjectSimpleAnotation");
System.out.println(simple);
ctx.close();
}
}
當中的 spring-config.xml 並不需要做任何 <bean></bean>的宣告
只要加上之前所提過的
<context:annotation-config/>
<context:component-scan base-package="com.test" />
即可
執行結果:
Name :John Smith
Age:37
Age in Seconds: 1103760000
Height: 1.78
Is Programmer?: true
還可以再使用一種? 使用 Annotation 搭配 SpEL 取值!!!
【第四種】
使用範例:
injectSimpleConfig2.java
package com.test;
import org.springframework.stereotype.Component;
/**
* Created by Hsu on 2014/7/10.
*/
//標示紅色的部分,宣告此一class 為一個 spring 用的 component ,並指定一個名稱
//相當於 <bean name=”injectSimpleConfig2” class=”com.test.InjectSimpleConfig2” />
@Component("injectSimpleConfig2")
public class InjectSimpleConfig2 {
private String name = "John Smith";
private int age = 35;
private float height = 1.78f;
private boolean programmer = true;
private Long ageInSeconds = 1103760000L;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public boolean isProgrammer() {
return programmer;
}
public void setProgrammer(boolean programmer) {
this.programmer = programmer;
}
public Long getAgeInSeconds() {
return ageInSeconds;
}
public void setAgeInSeconds(Long ageInSeconds) {
this.ageInSeconds = ageInSeconds;
}
}
InjectSimpleSpel2.java
package com.test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.stereotype.Service;
/**
* Created by Hsu on 2014/7/10.
*/
@Service("injectSimpleSpel2")
public class InjectSimpleSpel2 {
@Value("#{injectSimpleConfig2.name}")
private String name;
@Value("#{injectSimpleConfig2.age + 1}")
private int age;
@Value("#{injectSimpleConfig2.height}")
private float height;
@Value("#{injectSimpleConfig2.programmer}")
private boolean programmer;
@Value("#{injectSimpleConfig2.ageInSeconds}")
private Long ageInSeconds;
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("resource/spring-config.xml");
ctx.refresh();
InjectSimpleSpel2 simple = (InjectSimpleSpel2)ctx.getBean("injectSimpleSpel2");
System.out.println(simple);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public boolean isProgrammer() {
return programmer;
}
public void setProgrammer(boolean programmer) {
this.programmer = programmer;
}
public Long getAgeInSeconds() {
return ageInSeconds;
}
public void setAgeInSeconds(Long ageInSeconds) {
this.ageInSeconds = ageInSeconds;
}
@Override
public String toString(){
return "Name :" + name + "\n"
+ "Age:" + age + "\n"
+ "Age in Seconds: " + ageInSeconds + "\n"
+ "Height: " + height + "\n"
+ "Is Programmer?: " + programmer;
}
}
最後一個方法的 spring-config.xml 的配置法同第三種方法哦,一樣不需要設定 <bean></bean>
執行結果:
Name :John Smith
Age:36
Age in Seconds: 1103760000
Height: 1.78
Is Programmer?: true
補充:
What's the difference between @Component, @Repository & @Service annotations in Spring?
From Spring Documentation:
In Spring 2.0 and later, the @Repository annotation is a marker for any class that fulfills the role or stereotype (also known as Data Access Object or DAO) of a repository. Among the uses of this marker is the automatic translation of exceptions.
Spring 2.5 introduces further stereotype annotations: @Component, @Service, and @Controller. @Component is a generic stereotype for any Spring-managed component. @Repository, @Service, and @Controller are specializations of @Component for more specific use cases, for example, in the persistence, service, and presentation layers, respectively.
Therefore, you can annotate your component classes with @Component, but by annotating them with @Repository, @Service, or @Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts.
Thus, if you are choosing between using @Component or @Service for your service layer, @Service is clearly the better choice. Similarly, as stated above, @Repository is already supported as a marker for automatic exception translation in your persistence layer.
| Annotation | Meaning |
+------------+-----------------------------------------------------+
| @Component | generic stereotype for any Spring-managed component |
| @Repository| stereotype for persistence layer |
| @Service | stereotype for service layer |
| @Controller| stereotype for presentation layer (spring-mvc) |
They are almost the same - all of them mean that the class is a Spring bean. @Service, @Repository and @Controller are specialized @Components. You can choose to perform specific actions with them. For example:
Another thing is that you designate the components semantically to different layers.
One thing that @Component offers is that you can annotate other annotations with it, and then use them the same way as @Service.
For example recently I made:
Spring 2.5 introduces further stereotype annotations: @Component, @Service and @Controller. @Component serves as a generic stereotype for any Spring-managed component; whereas, @Repository, @Service, and @Controller serve as specializations of @Component for more specific use cases (e.g., in the persistence, service, and presentation layers, respectively). What this means is that you can annotate your component classes with @Component, but by annotating them with @Repository, @Service, or @Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. Of course, it is also possible that @Repository, @Service, and @Controller may carry additional semantics in future releases of the Spring Framework. Thus, if you are making a decision between using @Component or @Service for your service layer, @Service is clearly the better choice. Similarly, as stated above, @Repository is already supported as a marker for automatic exception translation in your persistence layer.
@Component – Indicates a auto scan component.
@Repository – Indicates DAO component in the persistence layer.
@Service – Indicates a Service component in the business layer.
@Controller – Indicates a controller component in the presentation layer.
簡單說,東西是一樣的,依使用的需求訂立不同的別名