Spring 是輕量級的開源的 JavaEE 框架,
Spring有兩個核心部分IOC 和 Aop
- IOC(Inversion of Control):控制反轉,把創建物件程序交給 Spring 進行管理
- Aop(Aspect Oriented Programming):面向切面編程,不修改源代碼進行功能增強
Spring特點:
- 方便解耦,簡化開發
- Aop 編程支持
- 方便程式測驗
- 方便和其他框架進行整合
- 方便進行事務操作
- 降低 API 開發難度
本篇介紹主要介紹IOC
IOC底層原理:
- 配置xml檔案,配置自己想要創建的物件
- 創建工廠類,在工廠類中通過xml決議獲取組態檔中的class屬性值,再通過反射機制創建物件從而獲得物件實體,
Spring 提供了兩種 IOC 容器實作方式(兩個介面):
- BeanFactory:IOC 容器基本實作,是 Spring 內部的使用介面,一般不提供開發人員進行使用(想用也不是不可以拉)
- 加載組態檔時候不會創建物件,在獲取物件(使用)才去創建物件
- ApplicationContext:BeanFactory 介面的子介面,提供更多更強大的功能,一般由開發人員進行使用
- 加載組態檔時候就會把在組態檔物件進行創建
Bean 管理
Bean 管理指的是兩個操作
- Spring 創建物件
- Spirng 注入屬性
其有兩種實作方式
- 基于 xml 組態檔方式實作
- 基于注解方式實作
基于xml方式的Bean管理
-
在 spring 組態檔中,使用 bean 標簽,標簽里面添加對應屬性,就可以實作物件創建
-
在 bean 標簽有很多屬性,常用的屬性有
id 屬性:唯一標識
class 屬性:類全路徑(包類路徑)
-
創建物件時候,默認執行無引數構造方法完成物件創建
首先匯入相關jar包,實際版本以自己的spring版本為最終結果,我的Spring版本是5.2.6
spring-expression-5.2.6.RELEASE.jar
commons-logging-1.1.1.jar
spring-beans-5.2.6.RELEASE.jar
spring-context-5.2.6.RELEASE.jar
spring-core-5.2.6.RELEASE.jar
使用set方法進行注入
-
創建類,定義屬性和對應的 set 方法
public class Book { //創建屬性 private String bname; private String bauther; private String baddress; //創建屬性對應的set方法 public void setBname(String bname) { this.bname = bname; } public void setBauther(String bauther) { this.bauther = bauther; } public void setBaddress(String baddress) { this.baddress = baddress; } } -
在 spring 組態檔配置創建物件和注入的屬性
<bean id="book" > <!--使用property完成屬性的注入 name:類里面屬性的名稱 value:向屬性注入的值 --> <property name="bname" value="https://www.cnblogs.com/xuzhuo123/p/易筋經"></property> <property name="bauther" value="https://www.cnblogs.com/xuzhuo123/p/達摩老祖"></property> <!--設定一個空值--> <property name="baddress"> <null/> </property>--> <!--屬性包含特殊符號 方法1 把<>進行轉義 <> 方法2 把帶特殊符號的內容寫到CDATA中 --> <property name="baddress"> <value><![CDATA[<<南京>>]]></value> </property> </bean>
注入其他型別的屬性:
注入屬性-空值::
<bean id="book" >
<!--設定一個空值-->
<property name="baddress">
<null/>
</property>-->
</bean>
注入屬性-包含特殊符號:
<bean id="book" >
<!--屬性包含特殊符號
方法1 把<>進行轉義 <>
方法2 把帶特殊符號的內容寫到CDATA中
-->
<property name="baddress">
<value><![CDATA[<<南京>>]]></value>
</property>
</bean>
注入屬性-外部bean
這里以UserServiceImpl類和UserDaoImpl類進行示例
- 創建兩個類 UserServiceImpl 類和 UserDaoImpl 類
- 在 service 呼叫 dao 里面的方法
- 在 spring 組態檔中進行配置
public class UserServiceImpl implements UserService{
//創建UserDao型別屬性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add ..........");
userDao.update();
}
}
<bean id="userService" >
<!--注入userDao物件
name屬性值:類里的屬性名稱
ref屬性:創建userDao物件bean標簽的id值,引入外部bean
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" ></bean>
注入屬性-內部bean
這里以部門(Dept)類和員工(Emp)類進行示例
//部門類
public class Dept {
private String danme;
public String getDanme() {
return danme;
}
public void setDanme(String danme) {
this.danme = danme;
}
}
//員工類
public class Emp {
private String ename;
private String egender;
//員工屬于某一個部門,使用物件的形式進行表示
private Dept dept;
public Dept getDept() {
return dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setEgender(String egender) {
this.egender = egender;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
<bean id="emp" >
<!--設定兩個普通屬性-->
<property name="ename" value="https://www.cnblogs.com/xuzhuo123/p/lucy"></property>
<property name="egender" value="https://www.cnblogs.com/xuzhuo123/p/woman"></property>
<!--設定物件型別的屬性-->
<property name="dept" >
<bean id="dept" >
<property name="danme" value="https://www.cnblogs.com/xuzhuo123/p/AC"></property>
</bean>
</property>
</bean>
注入屬性-集合:
public class Stu {
//陣列型別屬性
private String[] courses;
//List集合型別的屬性
private List<String> list;
//Map集合型別的屬性
private Map<String, String> maps;
//set集合型別的屬性
private Set<String> sets;
//Course型別的屬性
private List<Course> courseList;
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;
}
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
}
<!--集合型別屬性注入-->
<bean id="stu" >
<!--陣列型別屬性注入-->
<property name="courses">
<array>
<value>java</value>
<value>c++</value>
</array>
</property>
<!--list型別屬性注入-->
<property name="list">
<list>
<value>張三</value>
<value>小張</value>
</list>
</property>
<!--map型別屬性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="https://www.cnblogs.com/xuzhuo123/p/java"></entry>
<entry key="PHP" value="https://www.cnblogs.com/xuzhuo123/p/php"></entry>
</map>
</property>
<!--set型別屬性注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
<!--注入list集合型別,值是物件-->
<property name="courseList">
<list>
<ref bean="course1"/>
<ref bean="course2"/>
</list>
</property>
</bean>
<!--創建多個course物件-->
<bean id="course1" >
<property name="cname" value="https://www.cnblogs.com/xuzhuo123/p/Spring5"></property>
</bean>
<bean id="course2" >
<property name="cname" value="https://www.cnblogs.com/xuzhuo123/p/SpringMVC"></property>
</bean>
對于需要反復使用的屬性可以提取出來,以List為例
<?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">
<!--1 提取list集合型別屬性-->
<util:list id="bookList">
<value>易筋經</value>
<value>九陰真經</value>
<value>九陽神功</value>
</util:list>
<!--2 提取list集合型別屬性注入使用-->
<bean id="book" scope="prototype">
<property name="list" ref="bookList"></property>
</bean>
</beans>
xml自動裝配
<!--實作自動裝配
autowire屬性常用兩個值:
byName根據屬性名稱注入,注入bean的id值要和類屬性名稱一樣
byType根據屬性型別注入,相同型別的bean不能定義多個,不然會報錯
-->
<bean id="emp" autowire="byName"></bean>
<bean id="dept" ></bean>
xml引入外部屬性檔案
以資料庫配置為例,jdbc.properties的路徑在src下,其內容如下
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=root
則在xml檔案中,先引入context名稱空間,再引入外部屬性檔案,如下所示
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--引入外部屬性檔案-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" >
<property name="driverClassName" value="https://www.cnblogs.com/xuzhuo123/p/${prop.driverClass}"/>
<property name="url" value="https://www.cnblogs.com/xuzhuo123/p/${prop.url}"/>
<property name="username" value="https://www.cnblogs.com/xuzhuo123/p/${prop.userName}"/>
<property name="password" value="https://www.cnblogs.com/xuzhuo123/p/${prop.password}"/>
</bean>
</beans>
基于注解方式的Bean管理
注解是代碼特殊標記,格式:@注解名稱(屬性名稱=屬性值, 屬性名稱=屬性值...)
注解作用在類上面,方法上面,屬性上面
使用注解目的:簡化 xml 配置
有4個注解,分別為(1)@Component (2)@Service (3)@Controller (4)@Repository
以上四個注解功能是一樣的,都可以用來創建 bean 實體
基于注解方式實作物件創建
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--開啟組件掃描
1 如果掃描多個包,則在多個包中間使用逗號隔開
2 或者寫這些包的上層目錄
-->
<context:component-scan base-package="com.hnust.spring5"></context:component-scan>
<!--示例1
use-default-filters="false" 表示現在不使用默認filter而使用中間配置的filter
context:include-filter 設定掃描內容,該示例只掃描Controller注解
-->
<context:component-scan base-package="com.hnust.spring5" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例2
use-default-filters="false" 表示現在不使用默認filter而使用中間配置的filter
context:include-filter 設定不進行掃描的內容,該示例不掃描Controller注解,剩下全部掃描
-->
<context:component-scan base-package="com.hnust.spring5">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
//在注解里面的value屬性值可以省略不寫,默認值是類名稱并將其首字母小寫
@Service(value = "https://www.cnblogs.com/xuzhuo123/p/userService") //與<bean id="userService" />寫法類似
public class UserService {
//普通屬性注入
@Value(value = "https://www.cnblogs.com/xuzhuo123/p/abc")
private String name;
//定義Dao型別的屬性,不需要添加set方法,整個程序已經將set方法封裝好了
//添加注入屬性注解
@Autowired //根據型別進行自動注入
@Qualifier(value = "https://www.cnblogs.com/xuzhuo123/p/UserDaoImpl1")//根據名稱進行注入,和@Autowired搭配使用
private UserDao userDao;
public void add(){
System.out.println("service add ........"+name);
userDao.add();
}
}
完全使用注解,不使用xml組態檔
新建配置類,類名隨意,添加兩個注解,如下所示
@Configuration//把當前類作為配置類,代替xml組態檔
@ComponentScan(basePackages = {"com.hnust.spring5"})//開啟組件掃描
public class SpringConfig {
}
使用xml配置時,獲取背景關系物件的陳述句為ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
將其修改為ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);即可
Bean的生命周期
bean物件從誕生到銷毀總共經歷了7步,若去掉bean的后置處理器,則有5步,
示例代碼如下,首先定義Orders類
public class Orders {
public Orders() {
System.out.println("第一步 執行無引數構造器創建bean的實體");
}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 呼叫set方法設定屬性值");
}
//創建執行的初始化方法
public void initMethod(){
System.out.println("第四步 執行初始化方法");
}
//創建執行銷毀方法
public void destroyMethod(){
System.out.println("第七步 執行銷毀方法");
}
}
定義bean的后置處理器:
public class MyBean implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第三步 在初始化之前執行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步 在初始化之后執行的方法");
return bean;
}
}
配置xml:
<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.xsd">
<bean id="orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="https://www.cnblogs.com/xuzhuo123/p/手機"></property>
</bean>
<!--配置后置處理器-->
<bean id="myBeanPost" ></bean>
</beans>
測驗代碼:
@Test
public void testBean3(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第六步 獲取到了創建的bean實體物件");
//手動讓bean實體銷毀
context.close();
}
測驗結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/380180.html
標籤:Java
上一篇:Log4j2 重大漏洞,編譯好的log4j-2.15.0.jar包下載
下一篇:Java多執行緒學習隨記
