Spring框架的IOC和AOP

spring框架

QQ圖片20170511202629.png
  1. Ioc(Inversion of Control)控制反轉(zhuǎn)唆阿,在spring中BeanFactory是Ioc容器的核心借口邑飒,負(fù)責(zé)實(shí)例化徙缴,定位熄攘,配置應(yīng)用程序中的對(duì)象以及建立這些對(duì)象間的依賴(lài)姚淆。XmlBeanFactory實(shí)現(xiàn)BeanFactory接口孕蝉,通過(guò)獲取xml配置文件數(shù)據(jù),組成應(yīng)用對(duì)象以及對(duì)象間的依賴(lài)關(guān)系腌逢。
    三種注入方式:

(1)接口注入(不推薦)
(2)構(gòu)造方法注入(死的應(yīng)用)
(3)get降淮、set方式注入(常用)

(1)、 get搏讶、set的自動(dòng)安裝佳鳖,注入方式

autowire="defualt"
autowire=“byName”
autowire="bytype"'

例如:有兩個(gè)類(lèi)需要注入:

package org.jia;
  
  public class Order {
     private String orderNum;
    @SuppressWarnings("unused")
      private OrderItem orderitem;
  
      public OrderItem getOrderitem() {
         return orderitem;
     }
 
     public void setOrderitem(OrderItem orderitem) {
         this.orderitem = orderitem;
     }
 
     public String getOrderNum() {
         return orderNum;
     }
 
     public void setOrderNum(String orderNum) {
         this.orderNum = orderNum;
     }
     
}
package org.jia;
 
 public class OrderItem {
     private String orderdec;

     public String getOrderdec() {
         return orderdec;
    }

    public void setOrderdec(String orderdec) {
         this.orderdec = orderdec;
     }
}

getter&&setter方式第一種注入:defualt

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    <bean id="orderItem" class="org.jia.OrderItem">
        <property name="orderdec" value="item00001"></property>
    </bean>
    <bean id="order" class="org.jia.Order" >
        <!-----注入變量 名字必須與類(lèi)中的名字一樣------->
        <property name="orderNum" value="order000007"></property>
         <!--注入對(duì)象 名字為orderitem媒惕,所屬的類(lèi)的應(yīng)用id為orderItem-->
        <property name="orderitem" ref="orderItem"></property>
    
    --></bean>


</beans>

getter&&setter方式第二種注入:byName

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!--此時(shí)的id就必須與Order.java中所定義的OrderItem的對(duì)象名稱(chēng)一樣了系吩,不然就會(huì)找不到-->
    <bean id="orderitem" class="org.jia.OrderItem">
        <property name="orderdec" value="item00001"></property>
    </bean>
    <bean id="order" class="org.jia.Order" autowire="byName">
        <property name="orderNum" value="order000007"></property>
    </bean>
</beans>

getter&&setter方式第三種注入:byType

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!--按照byType注入則就與id沒(méi)有關(guān)系,可以隨便定義id 6饰怠J缑怠!但是不能出現(xiàn)多個(gè)此類(lèi)的id-->
    <bean id="orderitdfadafaem" class="org.jia.OrderItem">
        <property name="orderdec" value="item00001"></property>
    </bean>
    <bean id="order" class="org.jia.Order" autowire="byType">
        <property name="orderNum" value="order000007"></property>
    </bean>
</beans>

(2)面睛、關(guān)于構(gòu)造器的注入

autowire="constructor"

                                orderitem = item;
                                         }```
需要在Order.java中加入一個(gè)構(gòu)造器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="orderItem" class="org.jia.OrderItem">
<property name="orderdec" value="item00001"></property>
</bean>
<bean id="order" class="org.jia.Order" autowire="constructor">
<property name="orderNum" value="order000007"></property>
</bean>
</beans>

2.***aop***---代理
     **Spring Security**為spring Security為spring應(yīng)用提供了生命式的安全機(jī)制絮蒿。
    **Spring Boot**通過(guò)大量使用自動(dòng)配置技術(shù),可以取消大量的XML配置文件叁鉴,同時(shí)該框架提出了starter的概念土涝,用于簡(jiǎn)化pom文件』夏梗可以參考我的一系列博文:
### [《Spring Boot Cookbook》閱讀筆記](méi)(http://www.reibang.com/p/5ac18abc91f0)

**aop 應(yīng)用場(chǎng)景:**
>Authentication 權(quán)限
Caching 緩存
Context passing 內(nèi)容傳遞
Error handing 錯(cuò)誤處理
Lazy loading 懶加載
Debugging 調(diào)試
logging 但壮、tracing 、profiling and monitoring記錄跟蹤 優(yōu)化校準(zhǔn)
Performance optimization 性能優(yōu)化
Persistence 持久化
Resource pooling 資源池
Synchronization 同步
Transaction 事務(wù)


**如何使用Spring AOP**
>1.配置ProxyFactory常侣,顯式的設(shè)置advisors蜡饵、advice、target等
2.配置AutoProxyCreator胳施,
3.通過(guò)<aop:config>來(lái)配置
4.通過(guò)<aop:aspectj-autoproxy>使用AspectJ的注釋來(lái)表示通知以及切入點(diǎn)


**Spring提供了兩種方式實(shí)現(xiàn)代理:**
>1.JDKProxy動(dòng)態(tài)代理
2.Cglib
通過(guò)**<aop:config>**中的**proxy-target-class**屬性判斷溯祸,如果該屬性**被省略**或者為**false**---基于接口的代理起作用;如果該屬性為**true**---基于類(lèi)代理將起作用舞肆。


Spring中的AOP代理由Spring的IOC容器負(fù)責(zé)生成焦辅、管理,其依賴(lài)關(guān)系也有IOC容器負(fù)責(zé)管理椿胯。因此筷登,AOP代理可以直接使用容器中的其他bean實(shí)例作為目標(biāo),這種關(guān)系可以由IOC容器的依賴(lài)注入提供哩盲。Spring創(chuàng)建代理的規(guī)則為:

1前方、默認(rèn)使用Java動(dòng)態(tài)代理來(lái)創(chuàng)建AOP代理狈醉,這樣就可以為任何接口實(shí)例創(chuàng)建代理了

2、當(dāng)需要代理的類(lèi)不是代理接口的時(shí)候惠险,Spring會(huì)切換為使用CGLIB代理舔糖,也可強(qiáng)制使用CGLIB

AOP編程其實(shí)是很簡(jiǎn)單的事情,縱觀(guān)AOP編程莺匠,程序員只需要參與三個(gè)部分:

1金吗、定義普通業(yè)務(wù)組件

2、定義切入點(diǎn)趣竣,一個(gè)切入點(diǎn)可能橫切多個(gè)業(yè)務(wù)組件

3摇庙、定義增強(qiáng)處理,增強(qiáng)處理就是在A(yíng)OP框架為普通業(yè)務(wù)組件織入的處理動(dòng)作

**所以進(jìn)行AOP編程的關(guān)鍵就是定義切入點(diǎn)和定義增強(qiáng)處理遥缕,一旦定義了合適的切入點(diǎn)和增強(qiáng)處理卫袒,AOP框架將自動(dòng)生成AOP代理,即:代理對(duì)象的方法=增強(qiáng)處理+被代理對(duì)象的方法单匣。**


以下為簡(jiǎn)單實(shí)例:
aop.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

</beans>

兩個(gè)jar包:

1夕凝、aopalliance.jar

2、aspectjweaver.jar

開(kāi)始講解用Spring AOP的XML實(shí)現(xiàn)方式户秤,先定義一個(gè)接口:

public interface HelloWorld
{
void printHelloWorld();
void doPrint();
}


定義兩個(gè)接口實(shí)現(xiàn)類(lèi):

public class HelloWorldImpl1 implements HelloWorld
{
public void printHelloWorld()
{
System.out.println("Enter HelloWorldImpl1.printHelloWorld()");
}

public void doPrint()
{
    System.out.println("Enter HelloWorldImpl1.doPrint()");
    return ;
}

}


public class HelloWorldImpl2 implements HelloWorld
{
public void printHelloWorld()
{
System.out.println("Enter HelloWorldImpl2.printHelloWorld()");
}

public void doPrint()
{
    System.out.println("Enter HelloWorldImpl2.doPrint()");
    return ;
}

}

橫切關(guān)注點(diǎn)码秉,這里是打印時(shí)間:

public class TimeHandler
{
public void printTime()
{
System.out.println("CurrentTime = " + System.currentTimeMillis());
}
}

有這三個(gè)類(lèi)就可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Spring AOP了,看一下aop.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

    <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
    <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
    <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
    
    <aop:config>
        <aop:aspect id="time" ref="timeHandler">
            <aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
            <aop:before method="printTime" pointcut-ref="addAllMethod" />
            <aop:after method="printTime" pointcut-ref="addAllMethod" />
        </aop:aspect>
    </aop:config>

</beans>

寫(xiě)一個(gè)main函數(shù)調(diào)用一下:

public static void main(String[] args)
{
ApplicationContext ctx =
new ClassPathXmlApplicationContext("aop.xml");

HelloWorld hw1 = (HelloWorld)ctx.getBean("helloWorldImpl1");
HelloWorld hw2 = (HelloWorld)ctx.getBean("helloWorldImpl2");
hw1.printHelloWorld();
System.out.println();
hw1.doPrint();

System.out.println();
hw2.printHelloWorld();
System.out.println();
hw2.doPrint();

}

運(yùn)行結(jié)果為:

CurrentTime = 1446129611993
Enter HelloWorldImpl1.printHelloWorld()
CurrentTime = 1446129611993

CurrentTime = 1446129611994
Enter HelloWorldImpl1.doPrint()
CurrentTime = 1446129611994

CurrentTime = 1446129611994
Enter HelloWorldImpl2.printHelloWorld()
CurrentTime = 1446129611994

CurrentTime = 1446129611994
Enter HelloWorldImpl2.doPrint()
CurrentTime = 1446129611994

看到給HelloWorld接口的兩個(gè)實(shí)現(xiàn)類(lèi)的所有方法都加上了代理鸡号,代理內(nèi)容就是打印時(shí)間
**基于Spring的AOP使用其他細(xì)節(jié)**
1转砖、增加一個(gè)橫切關(guān)注點(diǎn),打印日志鲸伴,Java類(lèi)為:

public class LogHandler
{
public void LogBefore()
{
System.out.println("Log before method");
}

public void LogAfter()
{
    System.out.println("Log after method");
}

}

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

    <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
    <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
    <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
    <bean id="logHandler" class="com.xrq.aop.LogHandler" />
    
    <aop:config>
        <aop:aspect id="time" ref="timeHandler" order="1">
            <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
            <aop:before method="printTime" pointcut-ref="addTime" />
            <aop:after method="printTime" pointcut-ref="addTime" />
        </aop:aspect>
        <aop:aspect id="log" ref="logHandler" order="2">
            <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
            <aop:before method="LogBefore" pointcut-ref="printLog" />
            <aop:after method="LogAfter" pointcut-ref="printLog" />
        </aop:aspect>
    </aop:config>

</beans>

測(cè)試類(lèi)不變府蔗,打印結(jié)果為:

CurrentTime = 1446130273734
Log before method
Enter HelloWorldImpl1.printHelloWorld()
Log after method
CurrentTime = 1446130273735

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl1.doPrint()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl2.printHelloWorld()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273737
Log before method
Enter HelloWorldImpl2.doPrint()
Log after method
CurrentTime = 1446130273737

要想讓logHandler在timeHandler前使用有兩個(gè)辦法:

(1)aspect里面有一個(gè)order屬性,order屬性的數(shù)字就是橫切關(guān)注點(diǎn)的順序

(2)把logHandler定義在timeHandler前面汞窗,Spring默認(rèn)以aspect的定義順序作為織入順序

2姓赤、我只想織入接口中的某些方法

修改一下pointcut的expression就好了:
```
<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
        
        <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
        <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
        <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
        <bean id="logHandler" class="com.xrq.aop.LogHandler" />
        
        <aop:config>
            <aop:aspect id="time" ref="timeHandler" order="1">
                <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.print*(..))" />
                <aop:before method="printTime" pointcut-ref="addTime" />
                <aop:after method="printTime" pointcut-ref="addTime" />
            </aop:aspect>
            <aop:aspect id="log" ref="logHandler" order="2">
                <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.do*(..))" />
                <aop:before method="LogBefore" pointcut-ref="printLog" />
                <aop:after method="LogAfter" pointcut-ref="printLog" />
            </aop:aspect>
        </aop:config>
</beans>
```
表示timeHandler只會(huì)織入HelloWorld接口print開(kāi)頭的方法,logHandler只會(huì)織入HelloWorld接口do開(kāi)頭的方法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仲吏,一起剝皮案震驚了整個(gè)濱河市不铆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜘矢,老刑警劉巖狂男,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件综看,死亡現(xiàn)場(chǎng)離奇詭異品腹,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)红碑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)舞吭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)泡垃,“玉大人,你說(shuō)我怎么就攤上這事羡鸥∶镅ǎ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵惧浴,是天一觀(guān)的道長(zhǎng)存和。 經(jīng)常有香客問(wèn)我,道長(zhǎng)衷旅,這世上最難降的妖魔是什么捐腿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮柿顶,結(jié)果婚禮上茄袖,老公的妹妹穿的比我還像新娘。我一直安慰自己嘁锯,他們只是感情好宪祥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著家乘,像睡著了一般蝗羊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仁锯,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天肘交,我揣著相機(jī)與錄音,去河邊找鬼扑馁。 笑死涯呻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的腻要。 我是一名探鬼主播复罐,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雄家!你這毒婦竟也來(lái)了效诅?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤趟济,失蹤者是張志新(化名)和其女友劉穎乱投,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體顷编,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡戚炫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了媳纬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片双肤。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡施掏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出茅糜,到底是詐尸還是另有隱情七芭,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布蔑赘,位于F島的核電站狸驳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缩赛。R本人自食惡果不足惜锌历,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望峦筒。 院中可真熱鬧究西,春花似錦、人聲如沸物喷。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)峦失。三九已至扇丛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尉辑,已是汗流浹背帆精。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隧魄,地道東北人卓练。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像购啄,于是被迫代替她去往敵國(guó)和親襟企。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容