-
什么是Bean管理
- Bean管理指的就是兩個操作:
- 由Spring創(chuàng)建對象
- SPring注入屬性
-
Bean管理操作有兩種方式
- 基于xml配置文件方式實現(xiàn)
- 基于注解方式實現(xiàn)
-
基于xml方式創(chuàng)建對象
<!--配置User類對象的創(chuàng)建--> <bean id="user" class="com.spring5.test.User"></bean>
- 在Spring配置文件中,使用bean標簽,標簽里面添加對應屬性扭仁,就可以實現(xiàn)對象的創(chuàng)建
- 在bean標簽有很多屬性晓折,介紹常用的屬性:
- id屬性:對應對象唯一的標識
- class屬性:類全路徑(包類路徑)
- name屬性:同id屬性,但是id屬性不能使用/呢簸,但name屬性中可以使用/
- 創(chuàng)建對象時矮台,默認執(zhí)行無參數(shù)構(gòu)造方式完成對象創(chuàng)建
基于xml方式注入屬性
DI:依賴注入乏屯,就是注入屬性
-
第一種注入方式:使用set方法進行注入
public class Book { private String bname; private String bauthor; public void setBname(String bname) { this.bname = bname; } public void setBauthor(String bauthor) { this.bauthor = bauthor; } @Override public String toString() { return "Book{" + "bname='" + bname + '\'' + ", bauthor='" + bauthor + '\'' + '}'; } }
<!--set方法注入屬性--> <bean id="book" class="com.spring5.test.Book"> <!-- 使用property完成屬性注入 name: 類屬性名稱 value: 向?qū)傩宰⑷氲闹? --> <property name="bname" value="bookName"></property> <property name="bauthor" value="fallbackcolt"></property> </bean>
-
第二種注入方式:使用有參數(shù)構(gòu)造方法進行注入
public class Orders { private String oname; private String address; public Orders(String oname, String address) { this.oname = oname; this.address = address; } @Override public String toString() { return "Orders{" + "oname='" + oname + '\'' + ", address='" + address + '\'' + '}'; } }
<!--有參構(gòu)造注入屬性--> <bean id="orders" class="com.spring5.test.Orders"> <constructor-arg name="oname" value="orderName"></constructor-arg> <constructor-arg name="address" value="orderAddress"></constructor-arg> </bean>
p名稱空間注入(了解)
使用p名稱空間注入,可以簡化基于xml配置方式
-
添加p名稱空間在配置文件中
-
進行屬性注入瘦赫,在bean標簽里面進行操作(p名稱屬性注入的類必須包含set方法)
- xml注入其他類型屬性
-
字面值
- null值
<!--null值--> <property name="address"> <null/> </property>
- 屬性值包含特殊符號
<!-- 屬性值包含特殊符號 1. 把<>進行轉(zhuǎn)義 2. 把特殊符號內(nèi)容寫到CDATA中 --> <property name="address" > <value><![CDATA[<<南京>>]]></value> </property>
-
注入屬性-外部bean
- 創(chuàng)建兩個類service類和dao類
public class UserService { // 創(chuàng)建USerDao類型屬性辰晕,生成set方法 private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
public class UserDaoImpl implements UserDao{ @Override public void update() { System.out.println("dao update......"); } }
- 在service調(diào)用dao里面的方法
public void add() { System.out.println("service add......"); userDao.update(); }
- 在Spring配置文件中進行配置
<!--service和dao對象的創(chuàng)建--> <bean id="userService" class="com.spring5.test.service.UserService"> <!-- 注入userDao對象 ref屬性(注入外部bean):創(chuàng)建userDao對象bean標簽的id值 --> <property name="userDao" ref="userDao"></property> </bean> <bean id="userDao" class="com.spring5.test.dao.UserDaoImpl"></bean>
-
注入屬性-內(nèi)部bean
- 一對多關(guān)系: 部門和員工
- 在實體類之間表示一對多關(guān)系,員工表示所屬部門确虱,使用對象類型屬性進行表示
public class Dept { private String dname; public void setDname(String dname) { this.dname = dname; } @Override public String toString() { return "Dept{" + "dname='" + dname + '\'' + '}'; } }
public class Emp { private String ename; private String gender; // 員工屬于某一個部門含友,使用對象形式表示 private Dept dept; public void setEname(String ename) { this.ename = ename; } public void setGender(String gender) { this.gender = gender; } public void setDept(Dept dept) { this.dept = dept; } @Override public String toString() { return "Emp{" + "ename='" + ename + '\'' + ", gender='" + gender + '\'' + ", dept=" + dept + '}'; } }
- 在Spring配置文件中進行配置
<!--內(nèi)部bean--> <bean id="emp" class="com.spring5.test.bean.Emp"> <property name="ename" value="fallbackcolt"></property> <property name="gender" value="male"></property> <property name="dept"> <bean id="dept" class="com.spring5.test.bean.Dept"> <property name="dname" value="保安部"></property> </bean> </property> </bean>
-
注入屬性-級聯(lián)賦值
-
在Spring配置文件中進行配置
<!--級聯(lián)賦值--> <!--第一種寫法,感覺與外部注入差不多--> <bean id="emp" class="com.spring5.test.bean.Emp"> <property name="ename" value="fallbackcolt"></property> <property name="gender" value="male"></property> <!--級聯(lián)賦值--> <property name="dept" ref="dept"></property> </bean> <bean id="dept" class="com.spring5.test.bean.Dept"> <property name="dname" value="財務部"></property> </bean> <!--第二種寫法--> <bean id="emp2" class="com.spring5.test.bean.Emp"> <property name="ename" value="fallbackcolt"></property> <property name="gender" value="male"></property> <!--級聯(lián)賦值--> <!-- 使用dept.dname的前提是校辩,Emp類必須有對應的getDept()方法 將dept2的值重新賦值為技術(shù)部 --> <property name="dept" ref="dept2"></property> <property name="dept.dname" value="技術(shù)部"></property> </bean> <!--創(chuàng)建新的Dept對象dept2窘问,并且初始化--> <bean id="dept2" class="com.spring5.test.bean.Dept"> <property name="dname"><null/></property> </bean>
-
在Emp類中添加
getDept()
方法public Dept getDept() { return dept; }
-
-
xml注入集合屬性
-
創(chuàng)建Stu類,定義數(shù)組召川、list南缓、map、set類型屬性荧呐,并生成對應是set方法
public class Stu { // 數(shù)組類型屬性 private String[] courses; // list集合類型屬性 private List<String> list; // map集合類型屬性 private Map<String, String> maps; // set集合類型屬性 private Set<String> sets; public void setCourses(String[] courses) { this.courses = courses; } public void setList(List<String> list) { this.list = list; } public void setMaps(Map<String, String> maps) { this.maps = maps; } public void setSets(Set<String> sets) { this.sets = sets; } @Override public String toString() { return "Stu{" + "courses=" + Arrays.toString(courses) + ", list=" + list + ", maps=" + maps + ", sets=" + sets + '}'; } }
-
在Spring配置文件中進行配置
<!--集合類型屬性注入--> <bean id="stu" class="com.spring5.test.collectiontype.Stu"> <!--數(shù)組類型屬性注入--> <property name="courses"> <!--list汉形、array標簽都可以--> <list> <value>java課程</value> <value>數(shù)據(jù)庫課程</value> </list> </property> <!--list類型屬性注入--> <property name="list"> <!--list、array標簽都可以--> <array> <value>張三</value> <value>李四</value> </array> </property> <!--map類型屬性注入--> <property name="maps"> <map> <entry key="JAVA" value="java"></entry> <entry key="PHP" value="php"></entry> </map> </property> <!--set類型屬性注入--> <property name="sets"> <set> <value>MySQl</value> <value>Redis</value> </set> </property> </bean>
-
在集合里面設(shè)置對象類型值
-
創(chuàng)建Course類
public class Course { // 課程名稱 private String cname; public void setCname(String cname) { this.cname = cname; } @Override public String toString() { return "Course{" + "cname='" + cname + '\'' + '}'; } }
-
將Stu類中添加CourseList屬性倍阐,并重寫
toString()
方法// 學生所學的多門課程 private List<Course> courseList; public void setCourseList(List<Course> courseList) { this.courseList = courseList; }
-
在Spring配置文件中設(shè)置對象屬性值
<!--在bean.xml中Stu對象中添加courseList屬性--> <!--注入list集合類型屬性概疆,值為Course對象--> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property>
<!--其中courseList中的值為下面兩個Course對象--> <!--創(chuàng)建多個Course對象--> <bean id="course1" class="com.spring5.test.collectiontype.Course"> <property name="cname" value="Spring5框架"></property> </bean> <bean id="course2" class="com.spring5.test.collectiontype.Course"> <property name="cname" value="MyBatis框架"></property> </bean>
-
-
把集合注入部分提取出來
-
新建Book類
public class Book { private List<String> list; public void setList(List<String> list) { this.list = list; } @Override public String toString() { return "Book{" + "list=" + list + '}'; } }
-
在Spring配置文件中引入名稱空間util
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> </beans>
-
使用util標簽完成list集合注入提取
<!--提取list集合類型屬性注入--> <util:list id="bookList"> <value>從零開始學JAVA</value> <value>從零開始學PYTHON</value> <value>從零開始學MySQL</value> </util:list> <!--提取list集合類型屬性注入使用--> <bean id="book" class="com.spring5.test.collectiontype.Book"> <property name="list" ref="bookList"></property> </bean>
-
FactoryBean
-
Spring有兩種類型bean,一種普通bean峰搪,另外一種工廠bean(FactoryBean)
普通bean:在配置文件中定義bean類型就是返回類型
-
工廠bean:在配置文件中定義bean類型可以和返回類型不一樣
-
創(chuàng)建類岔冀,讓這個類作為工廠bean,實現(xiàn)接口FactoryBean
public class MyBean implements FactoryBean<Course> { }
-
實現(xiàn)接口里的方法概耻,在實現(xiàn)的方法中定義返回的bean類型
// 定義返回bean @Override public Course getObject() throws Exception { Course course = new Course(); course.setCname("test"); return course; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); }
-
bean作用域
- 在Spring里面使套,設(shè)置bean實例是單實例還是多實例
- 在Spring里面,默認情況下bean是單實例對象
- 設(shè)置bean多實例對象
- 在Spring配置文件中鞠柄,bean標簽中侦高,有屬性
scope
用于設(shè)置單實例或者多實例 -
scope
屬性值:- 默認值:singleton,表示單實例對象
- prototype厌杜,表示多實例對象
- request奉呛,表示每一次http新的請求都會產(chǎn)生一個新的bean對象
- session,表示每一個獨立的session會有一個新的bean對象
-
singleton和prototype區(qū)別:
- singleton是單實例夯尽,prototype是多實例
- 設(shè)置scope值是singleton時瞧壮,加載Spring配置文件時,就會創(chuàng)建單實例對象
- 設(shè)置scope值是prototype時匙握,在調(diào)用
getBean()
方法才會創(chuàng)建多實例對象
- 在Spring配置文件中鞠柄,bean標簽中侦高,有屬性
bean的生命周期
-
生命周期
- 從對象創(chuàng)建到對象銷毀的過程
-
bean的生命周期
- 通過構(gòu)造器創(chuàng)建bean實例(無參數(shù)構(gòu)造)
- 為bean的屬性設(shè)置值和對其他bean的引用(調(diào)用set方法)
- 調(diào)用bean的初始化的方法(通過設(shè)置bean標簽中的init-method為聲明的方法進行配置)
- bean可以使用了(對象獲取到了)
- 當容器關(guān)閉的時候咆槽,調(diào)用bean的銷毀的方法((通過設(shè)置bean標簽中的destroy-method為聲明的方法進行配置)
-
演示bean的生命周期
-
新建Orders類
public class Orders { public Orders() { System.out.println("1.執(zhí)行了無參數(shù)構(gòu)造創(chuàng)建bean實例"); } private String oname; public void setOname(String oname) { this.oname = oname; System.out.println("2.調(diào)用set方法設(shè)置屬性的值"); } // 創(chuàng)建執(zhí)行初始化的方法 public void initMethod() { System.out.println("3.執(zhí)行初始化方法"); } // 創(chuàng)建執(zhí)行銷毀的方法 public void destroyMethod() { System.out.println("5.執(zhí)行銷毀的方法"); } }
-
配置bean.xml文件
<bean id="orders" class="com.spring5.test.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"> <property name="oname" value="PC"></property> </bean>
-
測試
@Test public void testOrders() { ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml"); Orders orders = context.getBean("orders", Orders.class); System.out.println("4.獲取創(chuàng)建的bean實例對象"); System.out.println(orders); // 手動執(zhí)行bean實例的銷毀 // ClassPathXmlApplicationContext才有close,ApplicationContext沒有close ((ClassPathXmlApplicationContext)context).close(); }
-
測試運行結(jié)果
1.執(zhí)行了無參數(shù)構(gòu)造創(chuàng)建bean實例
2.調(diào)用set方法設(shè)置屬性的值
3.執(zhí)行初始化方法
4.獲取創(chuàng)建的bean實例對象
com.spring5.test.bean.Orders@587e5365
5.執(zhí)行銷毀的方法Process finished with exit code 0
-
-
bean的后置處理器肺孤,加上后置處理器后bean的生命周期有7步
- 通過構(gòu)造器創(chuàng)建bean實例(無參數(shù)構(gòu)造)
- 為bean的屬性設(shè)置值和對其他bean的引用(調(diào)用set方法)
- 把bean實例傳遞給bean后置處理器的
postProcessBeforeInitialization
方法 - 調(diào)用bean的初始化的方法(通過設(shè)置bean標簽中的init-method為聲明的方法進行配置)
- 把bean實例傳遞給bean后置處理器的
postProcessAfterInitialization
方法 - bean可以使用了(對象獲取到了)
- 當容器關(guān)閉的時候罗晕,調(diào)用bean的銷毀的方法((通過設(shè)置bean標簽中的destroy-method為聲明的方法進行配置)
-
演示添加后置處理器效果
-
創(chuàng)建類济欢,實現(xiàn)接口
BeanPostProcessor
public class OrdersPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("a.在初始化之前執(zhí)行的方法"); return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("b.在初始化之后執(zhí)行的方法"); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } }
-
在bean.xml中配置后置處理器
<!--配置后置處理器--> <bean id="ordersPost" class="com.spring5.test.bean.OrdersPost"></bean>
-
測試運行結(jié)果
1.執(zhí)行了無參數(shù)構(gòu)造創(chuàng)建bean實例
2.調(diào)用set方法設(shè)置屬性的值
a.在初始化之前執(zhí)行的方法
3.執(zhí)行初始化方法
b.在初始化之后執(zhí)行的方法
4.獲取創(chuàng)建的bean實例對象
com.spring5.test.bean.Orders@305b7c14
5.執(zhí)行銷毀的方法Process finished with exit code 0
-
xml自動裝配
-
什么是自動裝配
根據(jù)指定裝配規(guī)則(屬性名稱或者屬性類型),Spring自動將匹配的屬性值進行注入
-
演示自動裝配過程
-
根據(jù)屬性名稱自動注入
<!-- 實現(xiàn)自動裝配 autowire: 配置自動裝配 |___byName: 根據(jù)屬性名稱注入小渊,注入bean的id值和類屬性名一樣 |___byType: 根據(jù)屬性類型注入 --> <bean id="emp" class="com.spring5.test.autowire.Emp" autowire="byName"> <!--<property name="dept" ref="dept"></property>--> </bean> <bean id="dept" class="com.spring5.test.autowire.Dept"></bean>
-
根據(jù)屬性類型自動注入
<bean id="emp" class="com.spring5.test.autowire.Emp" autowire="byType"> <!--<property name="dept" ref="dept"></property>--> </bean> <bean id="dept" class="com.spring5.test.autowire.Dept"></bean>
-
管理外部屬性文件
-
直接配置數(shù)據(jù)庫信息
配置druid連接池
引入druid連接池依賴jar包
-
配置bean.xml
<!--直接配置連接池--> <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/Test"></property> <property name="username" value="test"></property> <property name="password" value="123456"></property> </bean>
-
通過引入外部屬性文件配置數(shù)據(jù)庫連接池
-
創(chuàng)建外部屬性文件法褥,properties格式文件,寫數(shù)據(jù)庫信息
prop.driverClass=com.mysql.jdbc.Driver prop.url=jdbc:mysql://localhost:3306/Test prop.username=test prop.password=123456
-
把外部properties屬性文件引入到Spring配置文件中
-
引入context命名空間
<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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
-
在Spring配置文件中使用標簽引入外部屬性文件
<!--引入外部屬性文件--> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <!--配置連接池--> <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${prop.driverClass}"></property> <property name="url" value="${prop.url}"></property> <property name="username" value="${prop.username}"></property> <property name="password" value="${prop.password}"></property> </bean>
-
-
基于注解方式注入屬性
-
什么是注解
- 注解是代碼特殊標記酬屉,格式:
@注解名稱(屬性名稱=屬性值,屬性名稱=屬性值...)
- 使用注解半等,注解可以作用在類、方法以及屬性上面
- 使用注解的目的:可以簡化xml配置
- 注解是代碼特殊標記酬屉,格式:
-
Spring針對Bean管理中創(chuàng)建對象提供注解
-
@Component
呐萨,通用注解杀饵? -
@Service
,一般用于業(yè)務邏輯層谬擦,Service層 -
@Controller
切距,一般用于web層 @Repository,一般用于dao層惨远,持久層
上述四個注解功能是一樣的谜悟,都可以用來創(chuàng)建bean實例
-
-
基于注解方式實現(xiàn)對象創(chuàng)建
導入依賴
spring-aop-5.3.9.jar
-
開啟組件掃描
<!-- 開啟組件掃描 1. 如果掃描多個包,多個包使用逗號隔開 2. 掃描包的上層目錄 --> <!--<context:component-scan base-package="com.spring5.test.testdemo,com.spring5.test.dao"></context:component-scan>--> <context:component-scan base-package="com.spring5.test"></context:component-scan>
-
創(chuàng)建類北秽,在類上添加創(chuàng)建對象注解
/* 在注解里面value屬性值可以省略不寫葡幸,默認值為首字母小寫的類名稱 */ @Component(value = "userService") // <bean id="userService" class="..."></bean> public class UserService { public void add() { System.out.println("add......"); } }
-
開啟組件掃描細節(jié)配置
<!-- 示例1 use-default-filters="false" 表示不使用默認的filter context:include-filter 設(shè)置掃描的內(nèi)容 --> <context:component-scan base-package="com.spring5.test" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 示例2 context:exclude-filter 設(shè)置不掃描的內(nèi)容 --> <context:component-scan base-package="com.spring5.test"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
-
基于注解方式實現(xiàn)屬性注入
-
@AutoWired
:根據(jù)屬性類型進行自動注入- 把service和dao對象創(chuàng)建,在service和dao類添加創(chuàng)建對象注解
- 在service注入dao對象贺氓,在service類添加dao類型屬性蔚叨,在屬性上面
@Qualifier
:根據(jù)屬性名稱進行自動注入(和@AutoWired
一起使用,Qualifier(value="xxx")
)@Resource
:可以根據(jù)類型注入辙培,也可以根據(jù)名稱注入(高版本已經(jīng)移除該注解蔑水,@Resource
是javax的包,不是Spring的包)-
@Value
:注入普通類型屬性(@Value(value="xxx")
)public interface UserDao { public void add(); }
@Repository(value = "userDaoImpl1") public class UserDaoImpl implements UserDao{ @Override public void add() { System.out.println("userDaoImpl add..."); } }
// 在注解里面value屬性值可以省略不寫扬蕊,默認值為首字母小寫的類名稱 @Service(value = "userService") // <bean id="userService" class="..."></bean> public class UserService { // 定義dao類型屬性 // 不需要添加set方法 // 添加注入屬性注解 @Autowired @Qualifier(value = "userDaoImpl1") private UserDao userDao; @Value(value = "initNameValue") private String name; public void add() { System.out.println("name=" + name); System.out.println("userService add......"); userDao.add(); } }
-
-
完全注解開發(fā)
-
創(chuàng)建配置類肤粱,替代xml配置文件
@Configuration // 作為配置類,替代xml配置文件 @ComponentScan(basePackages = {"com.spring5.test"}) public class SpringConfig { }
-
編寫測試類
@Test public void addTest2() { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); }
com.spring5.test.service.UserService@57d7f8ca
name=initNameValue
userService add......
userDaoImpl add...Process finished with exit code 0
-