javascript
Spring基础知识和配置
Spring 框架兩大核心機(jī)制(IoC、AOP)
idea運(yùn)行spring中遇到的問(wèn)題參考 idea配置遇到的問(wèn)題
- IoC(控制反轉(zhuǎn))/ DI(依賴注入)
- AOP(面向切面編程)
Spring 是一個(gè)企業(yè)級(jí)開(kāi)發(fā)框架,是軟件設(shè)計(jì)層面的框架,優(yōu)勢(shì)在于可以將應(yīng)用程序進(jìn)行分層,開(kāi)發(fā)者可以自主選擇組件。
MVC:Struts2、Spring MVC
ORMapping:Hibernate、MyBatis、Spring Data
如何使用 IoC
- 創(chuàng)建 Maven 工程,pom.xml 添加依賴
- 創(chuàng)建實(shí)體類 Student
- 傳統(tǒng)的開(kāi)發(fā)方式,手動(dòng) new Student
- 通過(guò) IoC 創(chuàng)建對(duì)象,在配置文件中添加需要管理的對(duì)象,XML 格式的配置文件,文件名可以自定義。
- 從 IoC 中獲取對(duì)象,通過(guò) id 獲取。
配置文件
-
通過(guò)配置 bean 標(biāo)簽來(lái)完成對(duì)象的管理。
-
id:對(duì)象名。
-
class:對(duì)象的模版類(所有交給 IoC 容器來(lái)管理的類必須有無(wú)參構(gòu)造函數(shù),因?yàn)?Spring 底層是通過(guò)反射機(jī)制來(lái)創(chuàng)建對(duì)象,調(diào)用的是無(wú)參構(gòu)造)
-
-
對(duì)象的成員變量通過(guò) property 標(biāo)簽完成賦值。
- name:成員變量名。
- value:成員變量值(基本數(shù)據(jù)類型,String 可以直接賦值,如果是其他引用類型,不能通過(guò) value 賦值)
- ref:將 IoC 中的另外一個(gè) bean 賦給當(dāng)前的成員變量(DI)
通過(guò)運(yùn)行時(shí)類獲取 bean
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Student student = (Student) applicationContext.getBean(Student.class); System.out.println(student);這種方式存在一個(gè)問(wèn)題,配置文件中一個(gè)數(shù)據(jù)類型的對(duì)象只能有一個(gè)實(shí)例,否則會(huì)拋出異常,因?yàn)闆](méi)有唯一的 bean。
通過(guò)有參構(gòu)造創(chuàng)建 bean
- 在實(shí)體類中創(chuàng)建對(duì)應(yīng)的有參構(gòu)造函數(shù)。
- 配置文件
給 bean 注入集合
<bean id="student" class="com.southwind.entity.Student"><property name="id" value="2"></property><property name="name" value="李四"></property><property name="age" value="33"></property><property name="addresses"><list><ref bean="address"></ref><ref bean="address2"></ref></list></property> </bean><bean id="address" class="com.southwind.entity.Address"><property name="id" value="1"></property><property name="name" value="科技路"></property> </bean><bean id="address2" class="com.southwind.entity.Address"><property name="id" value="2"></property><property name="name" value="高新區(qū)"></property> </bean>scope 作用域
Spring 管理的 bean 是根據(jù) scope 來(lái)生成的,表示 bean 的作用域,共4種,默認(rèn)值是 singleton。
- singleton:單例,表示通過(guò) IoC 容器獲取的 bean 是唯一的。
- prototype:原型,表示通過(guò) IoC 容器獲取的 bean 是不同的。
- request:請(qǐng)求,表示在一次 HTTP 請(qǐng)求內(nèi)有效。
- session:回話,表示在一個(gè)用戶會(huì)話內(nèi)有效。
request 和 session 只適用于 Web 項(xiàng)目,大多數(shù)情況下,使用單例和原型較多。
prototype 模式當(dāng)業(yè)務(wù)代碼獲取 IoC 容器中的 bean 時(shí),Spring 才去調(diào)用無(wú)參構(gòu)造創(chuàng)建對(duì)應(yīng)的 bean。
singleton 模式無(wú)論業(yè)務(wù)代碼是否獲取 IoC 容器中的 bean,Spring 在加載 spring.xml 時(shí)就會(huì)創(chuàng)建 bean。
Spring 的繼承
與 Java 的繼承不同,Java 是類層面的繼承,子類可以繼承父類的內(nèi)部結(jié)構(gòu)信息;Spring 是對(duì)象層面的繼承,子對(duì)象可以繼承父對(duì)象的屬性值。
<bean id="student2" class="com.southwind.entity.Student"><property name="id" value="1"></property><property name="name" value="張三"></property><property name="age" value="22"></property><property name="addresses"><list><ref bean="address"></ref><ref bean="address2"></ref></list></property> </bean><bean id="address" class="com.southwind.entity.Address"><property name="id" value="1"></property><property name="name" value="科技路"></property> </bean><bean id="address2" class="com.southwind.entity.Address"><property name="id" value="2"></property><property name="name" value="高新區(qū)"></property> </bean><bean id="stu" class="com.southwind.entity.Student" parent="student2"><property name="name" value="李四"></property> </bean>Spring 的繼承關(guān)注點(diǎn)在于具體的對(duì)象,而不在于類,即不同的兩個(gè)類的實(shí)例化對(duì)象可以完成繼承,前提是子對(duì)象必須包含父對(duì)象的所有屬性,同時(shí)可以在此基礎(chǔ)上添加其他的屬性。
Spring 的依賴
與繼承類似,依賴也是描述 bean 和 bean 之間的一種關(guān)系,配置依賴之后,被依賴的 bean 一定先創(chuàng)建,再創(chuàng)建依賴的 bean,A 依賴于 B,先創(chuàng)建 B,再創(chuàng)建 A。
<?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-3.2.xsd"><bean id="student" class="com.southwind.entity.Student" depends-on="user"></bean><bean id="user" class="com.southwind.entity.User"></bean></beans>Spring 的 p 命名空間
p 命名空間是對(duì) IoC / DI 的簡(jiǎn)化操作,使用 p 命名空間可以更加方便的完成 bean 的配置以及 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"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd "><bean id="student" class="com.southwind.entity.Student" p:id="1" p:name="張三" p:age="22" p:address-ref="address"></bean><bean id="address" class="com.southwind.entity.Address" p:id="2" p:name="科技路"></bean></beans>Spring 的工廠方法
IoC 通過(guò)工廠模式創(chuàng)建 bean 的方式有兩種:
- 靜態(tài)工廠方法
- 實(shí)例工廠方法
靜態(tài)工廠方法
package com.southwind.entity;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class Car {private long id;private String name; } package com.southwind.factory;import com.southwind.entity.Car;import java.util.HashMap; import java.util.Map;public class StaticCarFactory {private static Map<Long, Car> carMap;static{carMap = new HashMap<Long, Car>();carMap.put(1L,new Car(1L,"寶馬"));carMap.put(2L,new Car(2L,"奔馳"));}public static Car getCar(long id){return carMap.get(id);} } <!-- 配置靜態(tài)工廠創(chuàng)建 Car --> <bean id="car" class="com.southwind.factory.StaticCarFactory" factory-method="getCar"><constructor-arg value="2"></constructor-arg> </bean>實(shí)例工廠方法
package com.southwind.factory;import com.southwind.entity.Car;import java.util.HashMap; import java.util.Map;public class InstanceCarFactory {private Map<Long, Car> carMap;public InstanceCarFactory(){carMap = new HashMap<Long, Car>();carMap.put(1L,new Car(1L,"寶馬"));carMap.put(2L,new Car(2L,"奔馳"));}public Car getCar(long id){return carMap.get(id);} } <!-- 配置實(shí)例工廠 bean --> <bean id="carFactory" class="com.southwind.factory.InstanceCarFactory"></bean><!-- 賠償實(shí)例工廠創(chuàng)建 Car --> <bean id="car2" factory-bean="carFactory" factory-method="getCar"><constructor-arg value="1"></constructor-arg> </bean>IoC 自動(dòng)裝載(Autowire)
IoC 負(fù)責(zé)創(chuàng)建對(duì)象,DI 負(fù)責(zé)完成對(duì)象的依賴注入,通過(guò)配置 property 標(biāo)簽的 ref 屬性來(lái)完成,同時(shí) Spring 提供了另外一種更加簡(jiǎn)便的依賴注入方式:自動(dòng)裝載,不需要手動(dòng)配置 property,IoC 容器會(huì)自動(dòng)選擇 bean 完成注入。
自動(dòng)裝載有兩種方式:
- byName:通過(guò)屬性名自動(dòng)裝載
- byType:通過(guò)屬性的數(shù)據(jù)類型自動(dòng)裝載
byName
<bean id="cars" class="com.southwind.entity.Car"><property name="id" value="1"></property><property name="name" value="寶馬"></property> </bean><bean id="person" class="com.southwind.entity.Person" autowire="byName"><property name="id" value="11"></property><property name="name" value="張三"></property> </bean>byType
<bean id="car" class="com.southwind.entity.Car"><property name="id" value="2"></property><property name="name" value="奔馳"></property> </bean><bean id="person" class="com.southwind.entity.Person" autowire="byType"><property name="id" value="11"></property><property name="name" value="張三"></property> </bean>byType 需要注意,如果同時(shí)存在兩個(gè)及以上的符合條件的 bean 時(shí),自動(dòng)裝載會(huì)拋出異常。
AOP
AOP:Aspect Oriented Programming 面向切面編程。
AOP 的優(yōu)點(diǎn):
- 降低模塊之間的耦合度。
- 使系統(tǒng)更容易擴(kuò)展。
- 更好的代碼復(fù)用。
- 非業(yè)務(wù)代碼更加集中,不分散,便于統(tǒng)一管理。
- 業(yè)務(wù)代碼更加簡(jiǎn)潔存粹,不參雜其他代碼的影響。
AOP 是對(duì)面向?qū)ο缶幊痰囊粋€(gè)補(bǔ)充,在運(yùn)行時(shí),動(dòng)態(tài)地將代碼切入到類的指定方法、指定位置上的編程思想就是面向切面編程。將不同方法的同一個(gè)位置抽象成一個(gè)切面對(duì)象,對(duì)該切面對(duì)象進(jìn)行編程就是 AOP。
如何使用?
- 創(chuàng)建 Maven 工程,pom.xml 添加
- 創(chuàng)建一個(gè)計(jì)算器接口 Cal,定義4個(gè)方法。
- 創(chuàng)建接口的實(shí)現(xiàn)類 CalImpl。
上述代碼中,日志信息和業(yè)務(wù)邏輯的耦合性很高,不利于系統(tǒng)的維護(hù),使用 AOP 可以進(jìn)行優(yōu)化,如何來(lái)實(shí)現(xiàn) AOP?使用動(dòng)態(tài)代理的方式來(lái)實(shí)現(xiàn)。
給業(yè)務(wù)代碼找一個(gè)代理,打印日志信息的工作交個(gè)代理來(lái)做,這樣的話業(yè)務(wù)代碼就只需要關(guān)注自身的業(yè)務(wù)即可。
package com.southwind.utils;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays;public class MyInvocationHandler implements InvocationHandler {//接收委托對(duì)象private Object object = null;//返回代理對(duì)象public Object bind(Object object){this.object = object;return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(method.getName()+"方法的參數(shù)是:"+ Arrays.toString(args));Object result = method.invoke(this.object,args);System.out.println(method.getName()+"的結(jié)果是"+result);return result;} }以上是通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn) AOP 的過(guò)程,比較復(fù)雜,不好理解,Spring 框架對(duì) AOP 進(jìn)行了封裝,使用 Spring 框架可以用面向?qū)ο蟮乃枷雭?lái)實(shí)現(xiàn) AOP。
Spring 框架中不需要?jiǎng)?chuàng)建 InvocationHandler,只需要?jiǎng)?chuàng)建一個(gè)切面對(duì)象,將所有的非業(yè)務(wù)代碼在切面對(duì)象中完成即可,Spring 框架底層會(huì)自動(dòng)根據(jù)切面類以及目標(biāo)類生成一個(gè)代理對(duì)象。
LoggerAspect
package com.southwind.aop;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component;import java.util.Arrays;@Aspect @Component public class LoggerAspect {@Before(value = "execution(public int com.southwind.utils.impl.CalImpl.*(..))")public void before(JoinPoint joinPoint){//獲取方法名String name = joinPoint.getSignature().getName();//獲取參數(shù)String args = Arrays.toString(joinPoint.getArgs());System.out.println(name+"方法的參數(shù)是:"+ args);}@After(value = "execution(public int com.southwind.utils.impl.CalImpl.*(..))")public void after(JoinPoint joinPoint){//獲取方法名String name = joinPoint.getSignature().getName();System.out.println(name+"方法執(zhí)行完畢");}@AfterReturning(value = "execution(public int com.southwind.utils.impl.CalImpl.*(..))",returning = "result")public void afterReturning(JoinPoint joinPoint,Object result){//獲取方法名String name = joinPoint.getSignature().getName();System.out.println(name+"方法的結(jié)果是"+result);}@AfterThrowing(value = "execution(public int com.southwind.utils.impl.CalImpl.*(..))",throwing = "exception")public void afterThrowing(JoinPoint joinPoint,Exception exception){//獲取方法名String name = joinPoint.getSignature().getName();System.out.println(name+"方法拋出異常:"+exception);}}LoggerAspect 類定義處添加的兩個(gè)注解:
- @Aspect:表示該類是切面類。
- @Component:將該類的對(duì)象注入到 IoC 容器。
具體方法處添加的注解:
@Before:表示方法執(zhí)行的具體位置和時(shí)機(jī)。
CalImpl 也需要添加 @Component,交給 IoC 容器來(lái)管理。
package com.southwind.utils.impl;import com.southwind.utils.Cal; import org.springframework.stereotype.Component;@Component public class CalImpl implements Cal {public int add(int num1, int num2) {int result = num1+num2;return result;}public int sub(int num1, int num2) {int result = num1-num2;return result;}public int mul(int num1, int num2) {int result = num1*num2;return result;}public int div(int num1, int num2) {int result = num1/num2;return result;} }spring.xml 中配置 AOP。
<?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:aop="http://www.springframework.org/schema/aop"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd "><!-- 自動(dòng)掃描 --><context:component-scan base-package="com.southwind"></context:component-scan><!-- 是Aspect注解生效,為目標(biāo)類自動(dòng)生成代理對(duì)象 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>context:component-scan 將 com.southwind 包中的所有類進(jìn)行掃描,如果該類同時(shí)添加了 @Component,則將該類掃描到 IoC 容器中,即 IoC 管理它的對(duì)象。
aop:aspectj-autoproxy 讓 Spring 框架結(jié)合切面類和目標(biāo)類自動(dòng)生成動(dòng)態(tài)代理對(duì)象。
- 切面:橫切關(guān)注點(diǎn)被模塊化的抽象對(duì)象。
- 通知:切面對(duì)象完成的工作。
- 目標(biāo):被通知的對(duì)象,即被橫切的對(duì)象。
- 代理:切面、通知、目標(biāo)混合之后的對(duì)象。
- 連接點(diǎn):通知要插入業(yè)務(wù)代碼的具體位置。
- 切點(diǎn):AOP 通過(guò)切點(diǎn)定位到連接點(diǎn)。
總結(jié)
以上是生活随笔為你收集整理的Spring基础知识和配置的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: idea配置Spring遇到的问题(Lo
- 下一篇: SpringMVC+Mybatis基础知