Spring
? 涉及的設(shè)計(jì)模式:?jiǎn)卫J剑?jiǎn)單工廠模式,代理模式,觀察者模式,反射,注解。。。。。
Spring配置文件文件頭
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
IOC 控制反轉(zhuǎn) ---- 將創(chuàng)建對(duì)象的權(quán)力由開(kāi)發(fā)者交 給 Spring(緩解對(duì)象和對(duì)象之間的耦合度)
? 在傳統(tǒng)模式下,對(duì)象的創(chuàng)建和賦值,都是由開(kāi)發(fā)者自己手動(dòng)完成,事實(shí)情況下,開(kāi)發(fā)者只關(guān)心如何獲取賦值好的對(duì)象,但是并不希望自己手動(dòng)進(jìn)行創(chuàng)建對(duì)象和賦值的事情(spring中所有的對(duì)象都是從實(shí)例工廠中自動(dòng)創(chuàng)建,涉及到簡(jiǎn)單工廠模式)
IOC底層原理
- xml解析(負(fù)責(zé)讀取配置文件中 Bean 的相關(guān)信息)
- 簡(jiǎn)單工廠模式(借助 BeanFactory 完成對(duì)象的實(shí)例化和返回)
- 反射(不使用 new 創(chuàng)建對(duì)象的根本原因)
簡(jiǎn)單工廠模式
優(yōu)點(diǎn):
- 設(shè)計(jì)與實(shí)現(xiàn)分離(開(kāi)發(fā)者不需要關(guān)心對(duì)象是如何創(chuàng)建出來(lái)的)
- 如果要拓展業(yè)務(wù),并不會(huì)影響之前的業(yè)務(wù),只需要拓展子類即可
IOC容器的兩種實(shí)現(xiàn)方式
- BeanFactory:是Spring內(nèi)部使用的接口,不建議給開(kāi)發(fā)人員使用,該容器加載配置文件時(shí),并不會(huì)創(chuàng)建響應(yīng)對(duì)象,當(dāng)開(kāi)發(fā)者嘗試獲取對(duì)象的時(shí)候,才會(huì)創(chuàng)建對(duì)象(類似懶漢模式,具有延遲加載的特性)
- ApplicationContext:BeanFactory的子接口,一般由開(kāi)發(fā)人員使用,該容器在加載配置文件的時(shí)候,就會(huì)創(chuàng)建對(duì)象(類似餓漢模式,不會(huì)出現(xiàn)并發(fā)安全問(wèn)題,線程安全)
DI 依賴注入 ---- 在你配置好 bean 的情況下,由 Spring 幫你完成對(duì)象的賦值
優(yōu)點(diǎn):
- 實(shí)現(xiàn)了接口和實(shí)現(xiàn)的分離
- 組件化的思想,分離關(guān)注點(diǎn),使用接口時(shí),不再關(guān)注實(shí)現(xiàn)
Spring 的 bean 管理
?Bean的生命周期
-
常規(guī)五步生命周期
? 通過(guò)構(gòu)造器創(chuàng)建 bean 實(shí)例 => 通過(guò)反射調(diào)用 setter 方法完成屬性賦值 => 調(diào)用 bean 的初始化方法 => 獲取 bean 實(shí)例 => 當(dāng)容器關(guān)閉的時(shí)候, 調(diào)用 bean 的銷毀方法
-
完整七步生命周期
? 通過(guò)構(gòu)造器創(chuàng)建 bean 實(shí)例 => 通過(guò)反射調(diào)用 setter 方法完成屬性賦值 => 在 bean 初始化之前調(diào)用后置處理器 => 調(diào)用 bean 的初始化方法 => 在 bean初始化之后調(diào)用后置處理器 => 獲取 bean 實(shí)例 => 當(dāng)容器關(guān)閉的時(shí)候, 調(diào)用 bean 的銷毀方法
// 后置處理器 Demo public class MyPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之前調(diào)用的處理器"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之后調(diào)用的處理器"); return bean; } }
bean的自動(dòng)裝配
? 自動(dòng)裝配:根據(jù) bean 的 name 或者 type 實(shí)現(xiàn)自動(dòng)裝配
- byName 根據(jù)屬性名稱自動(dòng)注入(注入的 bean 名稱要跟屬性名稱保持一致)
- byType 根據(jù)屬性的類型自動(dòng)注入
<!-- byName 方式 自動(dòng)裝配 bean-->
<!-- person 對(duì)象再實(shí)例化的時(shí)候,需要注入 dog 屬性,而 dog 屬性對(duì)應(yīng)的應(yīng)該是一個(gè) Dog 類對(duì)象的內(nèi)存地址-->
<!-- byName 會(huì)根據(jù)你的成員變量名稱,找到匹配的 id 的 bean-->
<bean id="person" class="com.iweb.entity.Person" autowire="byName" />
<bean id="dog" class="com.iweb.entity.Dog" />
<!-- byType 方式 根據(jù)成員變量的類型,自動(dòng)裝配 id 不需要和成員變量匹配-->
<bean id="person" class="com.iweb.entity.Person" autowire="byType" />
<bean id="dog" class="com.iweb.entity.Dog" />
<!-- 導(dǎo)入外部配置文件-->
<context:property-placeholder location="db.properties" />
<!-- 在 spring 中加載外部配置文件 使用${}傳參 以 druid 連接池為例-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
bean創(chuàng)建(IOC)
-
基于xml的配置方式
結(jié)構(gòu)分析
<bean id="person" class="com.iweb.entity.Person" scope="prototype"/>
id
對(duì)象的唯一標(biāo)識(shí),通過(guò) id 獲取 bean 實(shí)例class
對(duì)象所屬類的完整路徑,用于提供給 spring 借助反射完成的對(duì)象創(chuàng)建scope
表示單/多實(shí)例模式<!-- 屬性注入--> <bean id="dog" class="com.iweb.entity.Dog"> <property name="name" value="dog01"/> <property name="type" value="dogType01"/> </bean> <!-- 構(gòu)造注入,利用構(gòu)造函數(shù)實(shí)現(xiàn)注入 未解決,爆紅?。。。。。。?!--> <bean id="dog" class="com.iweb.entity.Dog"> <constructor-arg name="name" value="dog01"/> </bean> <!-- 空值注入,手動(dòng)注入空值--> <bean id="dog" class="com.iweb.entity.Dog"> <property name="name"><null/></property> </bean> <!-- 特殊符號(hào)注入--> <bean id="dog" class="com.iweb.entity.Dog"> <property name="name"> <value><![CDATA[(-.-)]]></value> </property> </bean> <!-- 外部 bean 注入(引用綁定)--> <bean id="dog" class="com.iweb.entity.Dog"> <property name="name" value="dog01" /> <property name="type" value="type01" /> </bean> <bean id="person" class="com.iweb.entity.Person"> <property name="dog" ref="dog" /> </bean> <!-- 內(nèi)部 bean 注入(只能在某一個(gè) bean 的內(nèi)部訪問(wèn)它,其他 bean 無(wú)法訪問(wèn)內(nèi)部bean)--> <bean id="person" class="com.iweb.entity.Person"> <property name="dog"> <bean class="com.iweb.entity.Dog"> <property name="name" value="dog01" /> <property name="type" value="type01" /> </bean> </property> </bean> <!-- 級(jí)聯(lián)賦值--> <bean id="person" class="com.iweb.entity.Person"> <property name="dog" ref="dog" /> <property name="dog.type" value="type01" /> <property name="dog.name" value="dog01" /> </bean> <bean id="dog" class="com.iweb.entity.Dog" /> <!-- 集合注入 => 數(shù)組, list, map, set--> <bean id="person" class="com.iweb.entity.Person"> <!-- 數(shù)組注入--> <property name="hobbiesArray"> <array> <value>games</value> <value>coding</value> </array> </property> <!-- list集合注入--> <property name="hobbiesList"> <list> <value>games</value> <value>coding</value> </list> </property> <!-- set集合注入--> <property name="hobbiesSet"> <set> <value>games</value> <value>coding</value> </set> </property> <!-- map集合注入--> <property name="hobbiesMap"> <map> <entry key="games" value="游戲" /> <entry key="coding" value="編碼" /> </map> </property> </bean> <!-- Spring中管理了兩種Bean 1. 普通Bean 在配置文件中定義的類型,與返回類型保持一致 2. FactoryBean 在配置文件中定義的類型和返回的類型可以不一致 表面上是 factoryBeanDemo 類, 實(shí)際上是該類下的 dog 類 原理類似于 @Configuration 和 @Bean 注解 --> <bean id="factoryBeanDemo" class="com.iweb.entity.FactoryBeanDemo" />
-
基于注解方式
Spring 對(duì) bean 的管理提供了幾種注解,注解的功能是一致的,都用來(lái)注冊(cè)bean,但是注解本身所代表的含義不同
注解 含義 @Component 普通注解 @Service 業(yè)務(wù)層注解 @Controller 控制器注解(SpringMVC使用) @Repostiory DAO層注解(如果是 mybatis 一般會(huì)使用 @Mapper 或者在 springboot 中使用 @MapperScan) @Configuration 配置類注解 @Bean 配置類 bean 返回注解 @Qualifier 在使用了@AutoWired 注解的前提下,指定目標(biāo) name 所對(duì)應(yīng)的 bean 進(jìn)行注入 @AutoWired 根據(jù)類型自動(dòng)裝配(注入) @Resource 可以選擇根據(jù)類型,或者 name 進(jìn)行注入,在注入目標(biāo)為接口類型的時(shí)候,如果接口只有一個(gè)實(shí)現(xiàn)類,可以直接通過(guò)類型注入,如果接口有多個(gè)實(shí)現(xiàn)類,可以配置 name 屬性, 實(shí)現(xiàn)通過(guò) name 指定注入 @Value 直接注入 @ComponentScan 注解掃描注解 @AutoWired 和 @Resource 區(qū)別:
- @AutoWired 來(lái)自于 spring @Resource 來(lái)自于 jdk 原生
- @AutoWired 是根據(jù)類型自動(dòng)獲取,如果想根據(jù) name 獲取,需要 @Qualifier 協(xié)助
- @Resource 是根據(jù)類型或 name 獲取,如果提供 name 屬性,則按照 name 獲取,如果不提供則按照 type 獲取
舉個(gè)栗子:
// service層代碼 // 等價(jià)于 <bean id="userService" class="com.iweb.service.Impl.UserServiceImpl" /> @Service(value = "userService") public class UserServiceImpl implements UserService { @Override public int add() { System.out.println("UserService => add()"); return 0; } } // mapper層代碼,定義兩個(gè)相同的子類,注冊(cè)bean @Repository(value = "userMapper01") public class UserMapperImpl01 implements UserMapper { @Override public int add() { System.out.println("UserMapperImpl01 => add()"); return 0; } } @Repository(value = "userMapper02") public class UserMapperImpl02 implements UserMapper { @Override public int add() { System.out.println("UserMapperImpl02 => add()"); return 0; } }
AOP面向切面編程
? AOP面向切面編程,但是AOP不等于 SpringAOP,SpringAOP 只是 AOP的一種實(shí)現(xiàn)方式而已,切面的內(nèi)容和主業(yè)務(wù)邏輯是沒(méi)有關(guān)系的,不管切面的數(shù)量有多少,都不會(huì)影響也不應(yīng)該影響主業(yè)務(wù)的運(yùn)行
注解方式配置AOP(底層:代理模式)
?要給AOP文件添加 @Component
和 @Aspect
注解
-
Before
前置增強(qiáng)在目標(biāo)方法錢植入增強(qiáng)處理
@Before(value = "execution(* com.iweb.mapper.UserMapper.add(..))") public void before(JoinPoint joinPoint){ System.out.println("UserProxy => before()"); System.out.println("準(zhǔn)備執(zhí)行" + joinPoint.getTarget() + "的方法:" + joinPoint.getSignature().getName()); }
-
afterReturning
后置增強(qiáng)在目標(biāo)方法正常執(zhí)行(無(wú)異常)后植入增強(qiáng)處理
@AfterReturning(value = "execution(* com.iweb.mapper.UserMapper.add(..))", returning = "returnValue") public void afterReturning(JoinPoint joinPoint,Object returnValue){ System.out.println("UserProxy => afterReturning()."); System.out.println(joinPoint.getTarget() + "的方法" + joinPoint.getSignature().getName() + "的返回值為" + returnValue); }
-
afterThrowing
異常拋出增強(qiáng)在目標(biāo)方法拋出異常的時(shí)候植入增強(qiáng)處理
@AfterThrowing(value = "execution(* com.iweb.mapper.UserMapper.add(..))",throwing = "exception") public void afterThrowing(JoinPoint joinPoint,Exception exception){ System.out.println("UserProxy => afterThrowing()"); System.out.println("調(diào)用" + joinPoint.getSignature().getName() + "方法發(fā)生異常" + exception.getMessage()); }
-
after
最終增強(qiáng)無(wú)論方法是否拋出異常,都會(huì)在目標(biāo)方法之后植入增強(qiáng)處理,類似于異常處理機(jī)制中 finally 塊的作用,一般用于釋放資源
@After(value = "execution(* com.iweb.mapper.UserMapper.add(..))") public void after(JoinPoint joinPoint){ System.out.println("UserProxy => after()"); System.out.println("調(diào)用" + joinPoint.getSignature().getName() + "方法結(jié)束"); }
-
around
環(huán)繞增強(qiáng)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-635439.html在目標(biāo)方法前后都可以植入增強(qiáng)處理,功能最強(qiáng)大的增強(qiáng)處理,可以獲取或修改目標(biāo)方法的參數(shù),返回值,甚至可以控制目標(biāo)方法是否執(zhí)行文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-635439.html
@Around(value = "execution(* com.iweb.mapper.UserMapper.add(..))") public Object around(ProceedingJoinPoint joinPoint){ System.out.println("UserProxy => around()"); try{ System.out.println("準(zhǔn)備執(zhí)行" + joinPoint.getTarget() + "方法" + joinPoint.getSignature().getName()); // 獲取目標(biāo)方法的返回值 Object result = joinPoint.proceed(); System.out.println("環(huán)繞增強(qiáng)處理之前的方法返回值為:" + result); return (Integer)result + 10086; }catch(Throwable e){ e.printStackTrace(); return null; } }
到了這里,關(guān)于Java后端07(Spring)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!