第一個Spring程序
1、創(chuàng)建項目
2涮较、導入jar包spring.jar
和commons-logging.jar
3稠鼻、創(chuàng)建一個javabean類
public class Hello {
public void hello(){
System.out.println("hello");
}
}
4、在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/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--
beans
一個bean代表一個類
所以beans就是很多個類
-->
<!--
一個類
id 標示符
class 類的全名
-->
<bean id="hello" class="spring.com.bxp.bean.Hello">
</bean>
</beans>
5狂票、創(chuàng)建測試類
public class Test {
public static void main(String[] args) {
//啟動spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//從spring容器中提取bean
Hello hello = (Hello) context.getBean("hello");
hello.hello();
}
}
IOC
概念:把對象的創(chuàng)建候齿,初始化,銷毀交給Spring容器來做闺属。
Spring創(chuàng)建對象的方式
1慌盯、構造函數
spring內部默認調用spring的構造函數創(chuàng)建對象
2、靜態(tài)工廠
(1)創(chuàng)建靜態(tài)工廠
public class HelloFactory {
public static Hello getInstance(){
return new Hello();
}
}
(2)配置工廠
<?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/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--
beans
一個bean代表一個類
所以beans就是很多個類
-->
<!--
一個類
id 標示符
class 類的全名
-->
<bean id="hello" class="spring.com.bxp.bean.Hello">
</bean>
<!-- 配置靜態(tài)工廠 -->
<bean id="hello2" class="spring.com.bxp.bean.HelloFactory" factory-method="getInstance"></bean>
</beans>
(3)測試
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) context.getBean("hello2");
hello.hello();
}
}
3掂器、實例工廠
(1)創(chuàng)建實例工廠(使用最多)
public class HelloFactory {
public Hello getInstance(){
return new Hello();
}
}
(2)配置實例工廠
<?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/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--
beans
一個bean代表一個類
所以beans就是很多個類
-->
<!--
一個類
id 標示符
class 類的全名
-->
<bean id="hello" class="spring.com.bxp.bean.Hello">
</bean>
<!-- 配置實例工廠 -->
<bean id="helloFactory" class="spring.com.bxp.bean.HelloFactory"></bean>
<!-- factory-bean對象工廠 factory-method對象工廠方法 -->
<bean id="hello3" factory-bean="helloFactory" factory-method="getInstance"></bean>
</beans>
(3)測試
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) context.getBean("hello3");
hello.hello();
}
}
使用別名
在applicationContext.xml文件中使用alias標簽
<bean id="hello" class="spring.com.bxp.bean.Hello">
</bean>
<alias name="hello" alias="he"/>
對象的創(chuàng)建時機
默認創(chuàng)建方式
<bean id="hello" class="spring.com.bxp.bean.Hello">
1亚皂、加加載配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
2、根據配置文件中的配置的bean創(chuàng)建對象国瓮,配置多少個bean灭必,創(chuàng)建多少個對象。
public Hello() {
// TODO Auto-generated constructor stub
System.out.println("構造方法 ");
}
3乃摹、獲取對象
Hello hello = (Hello) context.getBean("hello3");
延遲創(chuàng)建(配置lazy-init屬性)
<bean id="hello" lazy-init="true" class="spring.com.bxp.bean.Hello">
1禁漓、加加載配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
2、獲取對象
Hello hello = (Hello) context.getBean("hello3");
//獲取對象的同時創(chuàng)建對象
public Hello() {
// TODO Auto-generated constructor stub
System.out.println("構造方法 ");
}
意義
如果把lazy-init值改為true孵睬,在spring啟動的時候播歼,檢測不到任何問題,會存在任何問題肪康。所以一般情況下lazy-init的值為false荚恶。
如果一個bean中包含大量的數據撩穿,不希望bean過早的停留在內存中磷支,此時將lazy-init的值改為true
對象的scope
在默認情況下(scope為singleton)
在spring中創(chuàng)建的對象的單例的。將來service和dao層所有的類將放到spring中食寡,這兩層中類的實例都是單例的雾狈,不能將屬性聲明在屬性中,會出現線程安全問題抵皱。
scope為prototype:
<bean scope="prototype" id="hello" lazy-init="false" class="spring.com.bxp.bean.Hello">
lazy-init和prototype的結合
scope為prorotype善榛,lazy-init為true
時:在context.getBean()時候創(chuàng)建對象
scope為prorotype辩蛋,lazy-init為false時:在context.getBean()時候創(chuàng)建對象,lazy-init為false失效移盆。
scope為prorotype悼院,始終在context.getBean()時候創(chuàng)建對象
對象的創(chuàng)建和銷毀
1、創(chuàng)建對象
public class Hello {
public void init(){
System.out.println("初始化方法");
}
public void destorym(){
System.out.println("銷毀方法");
}
public void hello(){
System.out.println("hello");
}
public Hello() {
// TODO Auto-generated constructor stub
System.out.println("構造方法 ");
}
}
2咒循、在配置文件中進行配置
<bean id="hello" class="spring.com.bxp.bean.Hello"
lazy-init="false" init-method="init"
destroy-method="destorym">
執(zhí)行順序
1据途、調用構造函數創(chuàng)建對象
2、有spring內部調用init()
方法進行對象的初始化
3叙甸、執(zhí)行對象的方法
4颖医、由執(zhí)行context.coose()
方法時候,由spring內部調用destory()
方法
說明
1裆蒸、init()
方法由spring內部調用
2熔萧、只有在spring容器關閉的時候才會執(zhí)行,一般情況下spring容器是不會關閉的僚祷,只有在web容器銷毀的時候才關閉佛致。
3、如果bean的配置為scope="prototype"
久妆,則spring容器不負責銷毀晌杰。
IOC執(zhí)行流程
DI(依賴注入)
給屬性賦值
1、創(chuàng)建的對象Persion
public class Persion {
private long id;
private String name;
private List list;
private Set set;
private Map map;
private Properties pro;
private Hello hello;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getPro() {
return pro;
}
public void setPro(Properties pro) {
this.pro = pro;
}
public Hello getHello() {
return hello;
}
public void setHello(Hello hello) {
this.hello = hello;
}
}
2筷弦、在配置文件對屬性進行配置
<bean id="persion" class="spring.com.bxp.bean.Persion">
<!-- name:屬性, value:值肋演, 引用類型使用ref賦值 -->
<property name="id" value="3"></property>
<property name="name" value="張三"></property>
<property name="hello" ref="hello"></property>
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
<ref bean="hello"/>
</list>
</property>
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
<ref bean="hello"/>
</set>
</property>
<property name="pro">
<props>
<prop key="pro1">pro1</prop>
<prop key="pro2">pro2</prop>
</props>
</property>
<property name="map">
<map>
<entry key="entry1">
<value>entry1</value>
</entry>
<entry key="entry2">
<ref bean="hello"/>
</entry>
</map>
</property>
</bean>
<bean id="hello" class="spring.com.bxp.bean.Hello"
lazy-init="false" init-method="init"
destroy-method="destorym">
</bean>
步驟:
1、spring容器實例化persion和hello兩個bean對象
2烂琴、利用java的反射機制調用setter方法對屬性進行賦值爹殊。
3、調用context.getBean()
獲取對象奸绷。
如果配置了init()
方法梗夸,則先執(zhí)行setter方法,在執(zhí)行init方法
persion對象依賴于hello對象号醉,如果在hello的bean標簽上面加上lazy-init = true
的屬性將會失效反症,因為創(chuàng)建persion對象必須創(chuàng)建hello對象。
使用構造器進行賦值
public Persion(long id, String name) {
super();
this.id = id;
this.name = name;
}
在配置文件中
<bean id="persion" class="spring.com.bxp.bean.Persion">
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="張三"></constructor-arg>
</bean>
IOC和DI的意義:
實現了完全面向接口編程畔派,客戶端沒有必要考慮具體的實現類是什么铅碍。
注解
概念
1、用來解釋說明
2线椰、必須作用于類的某一部分
3胞谈、注解的作用于范圍(java,class,jvm)
4烦绳、注解解析器
自定義注解
類注解
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)//classInfo注解可以標注在類上
/**
* RetentionPolicy.SOURCE 只能在源代碼上使用
*RetentionPolicy.CLASS 可以在源代碼上和字節(jié)碼上進行使用
*RetentionPolicy.RUNTIME 可以使用在源代碼卿捎,字節(jié)碼,jvm中
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented //該注解能夠出現在幫助文檔中
public @interface ClassInfo {
String name() default "";//給該注解聲明一個屬性name径密,默認值為""
}
方法注解
@Target(ElementType.METHOD)//classInfo注解可以標注在類上
/**
* RetentionPolicy.SOURCE 只能在源代碼上使用
*RetentionPolicy.CLASS 可以在源代碼上和字節(jié)碼上進行使用
*RetentionPolicy.RUNTIME 可以使用在源代碼午阵,字節(jié)碼,jvm中
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented //該注解能夠出現在幫助文檔中
public @interface MethodInfo {
String value() default "";
}
測試類
@ClassInfo(name = "這是類")
public class MyClass {
@MethodInfo("這是方法")
public void fun(){
}
}
解析注解
public void parse() {
Class clazz = MyClass.class;
if (clazz.isAnnotationPresent(ClassInfo.class)) {
ClassInfo classInfo = (ClassInfo) clazz
.getAnnotation(ClassInfo.class);
System.out.println(classInfo.name());
}
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MethodInfo.class)) {
MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
System.out.println(methodInfo.value());
}
}
}
Spring中的注解
案例:
1享扔、創(chuàng)建兩個實體類Persion和Student
public class Persion {
@Resource(name = "student")
private Student student;
public void say(){
student.say();
}
}
public class Student {
public void say(){
System.out.println("student");
}
}
2趟庄、在配置文件中進行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="persion" class="spring.com.bxp.bean.Persion"></bean>
<bean id="student" class="spring.com.bxp.bean.Student"></bean>
<!--
啟動依賴注入的注解解析器
-->
<context:annotation-config></context:annotation-config>
</beans>
引入依賴注入的注解解析器需要的名稱空間
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
3、測試
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Persion persion = (Persion) context.getBean("persion");
persion.say();
}
注解依賴注入的步驟:
1伪很、啟動spring容器
2戚啥、spring容器內部創(chuàng)建兩個對象(Persion和Student)
3、當spring容器解析到<context:annotation-config></context:annotation-config>
時啟動依賴注入解析器
4锉试、spring容器在容器中查找所有的bean(Persion猫十,Student)
5、查看meigebean的每個屬性上是否有Resource注解
6呆盖、如果屬性上面有該注解拖云,則檢查是否有name屬性
7、如果沒有name屬性应又,則獲取標注的屬性的名稱宙项,然后將該名稱和sping容器中的id進行匹配,如果匹配成功株扛,則進行賦值尤筐。如果匹配不成功,則按照類型進行匹配洞就,如果匹配成功則賦值盆繁,如果不成功,則報錯旬蟋。
8油昂、如果有name屬性,則把name屬性的值解析出來倾贰,和spring容器中的id進行匹配冕碟,如果匹配成功,則賦值匆浙,如果不成功則報錯安寺。
綜上所述:xml的效率高于注解,但是注解書寫方便吞彤。
spring中定義的注解
1我衬、按照類型進行匹配
@Autowired //按照類型進行匹配
2、按照id進行匹配
@Autowired
@Qualifier("student")