Spring注入&AOP


歡迎大家訪問我的網站:www.ifueen.com

Spring注入&AOP

注入

Maven裏面注入Spring

創建最基本的Maven項目,進行依賴注入:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ifueen</groupId>
    <artifactId>spring-day02</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!--Spring的核心包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!--Context包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!--aop的包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!--切面的一個包(織入)-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.8</version>
        </dependency>

        <!-- Spring的測試包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.5.RELEASE</version>
            <!--scope:範圍,只能在test包中使用-->
            <!--<scope>test</scope>-->
        </dependency>
        <!--junit的測試支持-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/test/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

通過構造方法注入參數

<?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.xsd">
    <bean id="mybean" class="com.ifueen._02constructor.MyBean">

        <!-- 通過索引配置-->
        <!--<constructor-arg index="0" value="羅素"/>
        <constructor-arg index="1" value="3"/>-->

        <!-- 通過name配置 -->
        <!--<constructor-arg name="age" value="30"/>
        <constructor-arg name="name" value="愛倫坡"/>-->

        <!-- 通過類型進行配置-->
        <!--<constructor-arg type="java.lang.String" value="狄更斯"/>
        <constructor-arg type="java.lang.Integer" value="45"/>-->

        <!-- 直接根據參數順序進行配置,注意!參數順序一定要相對應-->
        <constructor-arg value="薩特"/>
        <constructor-arg value="30"/>
    </bean>
</beans>

集合&數組&其他屬性的注入

<?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.xsd">
    <bean id="otherBean" class="com.ifueen._03rest.OtherBean"/>
    <bean id="mybean" class="com.ifueen._03rest.MyBean">

    <!-- 一般簡單的屬性 -->
        
        <property name="id" value="1"/>
        <property name="name" value="山泥若"/>
        <property name="sex" value="true"/>
        <property name="salary" value="797979"/>

    <!-- 數組 -->
        <property name="arrays">
            <array>
                <value>愛倫坡</value>
                <value>伏爾泰</value>
                <value>羅素</value>
            </array>
        </property>

    <!-- List集合 -->
        <property name="list">
            <list>
                <value>婁燁</value>
                <value>王家衛</value>
                <value>李安</value>
            </list>
        </property>

    <!-- set集合 -->
        <property name="set">
            <set>
                <value>諾蘭</value>
                <value>昆汀</value>
                <value>斯皮爾伯格</value>
            </set>
        </property>

        <!-- List集合OtherBean-->
        <property name="otherBeanList">
            <list>
                <!-- 內部Bean -->
                <bean class="com.ifueen._03rest.OtherBean"/>
                <bean class="com.ifueen._03rest.OtherBean"/>
                <!-- 外部引用 -->
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
            </list>
        </property>

        <!-- Set集合OtherBean-->
        <property name="otherBeanSet">
            <list>
                <!-- 內部Bean -->
                <bean class="com.ifueen._03rest.OtherBean"/>
                <bean class="com.ifueen._03rest.OtherBean"/>
                <!-- 外部引用 -->
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
            </list>
        </property>

        <!-- 簡寫方式 -->
        <property name="props1">
            <value>
            drivenClassName=com.mysql.jdbc.Driver
            url=jdbc:mysql:///jpa
            username=root
            password=123456
            </value>
        </property>

        <!-- 標準寫法 -->
        <property name="props2">
            <props>
            <prop key="drivenClassName">com.mysql.jdbc.Driver</prop>
            <prop key="url">jdbc:mysql:///hello</prop>
            <prop key="username">root</prop>
            <prop key="password">123456</prop>
            </props>
        </property>

        <!-- Map集合 -->
        <property name="hashMap">
        <map>
            <entry key="電影" value="2001太空漫步"/>
            <entry key="導演" value="庫布里克"/>
        </map>
        </property>
    </bean>


</beans>

使用全註解

使用全註解的方式和之前SpringMVC的使用方式一模一樣

<?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"
       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:component-scan base-package="com.ifueen._04auto"/>
</beans>

只需要將掃描包路徑配置好,然後寫三層架構即可

AOP(面向切面編程)

概述

定義:面向切面編程(面向方面編程)

咱們的編程語言從原始機器語言 到過程語言 再到面向對象,從始至終的目的就是爲了讓代碼再加靈活,再加容易讓人理解,構建代碼更加簡單。

AOP的使用只存在於一些特定的場合(具有橫切邏輯的應用場合),橫切邏輯這個解釋可能比較抽象,咱們說得再具體一點,AOP可以用於事務管理,日誌管理,性能監測等地方

面試題:Spring是如何實現AOP?

Spring是使用代理模式來實現AOP的

代理模式分兩種:靜態代理和動態代理

靜態代理太過笨重,一般不太使用

動態代理

Spring提供了兩種方案:JDK和CGLTB

如果目標對象使用了接口就讓JDK來進行代理

如果目標對象沒有使用接口就讓CGLTB來進行代理

使用XML配置實現AOP

首先定義自定義的事務類(僞事務類)

package com.ifueen._05xmlaop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 自己準備的一個事務
 */
public class TxManager {

    public void begin(){
        System.out.println("開啓事務");
    }
    public void commit(){
        System.out.println("提交事務");
    }
    public void rollback(Throwable e){
        System.out.println("回滾事務,異常的原因爲"+e.getMessage());
    }
    public void close(){
        System.out.println("關閉資源");
    }

    public void around(ProceedingJoinPoint point){
        /*System.out.println(point.getArgs()); //參數
        System.out.println(point.getSignature()); //獲取方法的簽名
        System.out.println(point.getTarget().getClass());//真實目標對象
        System.out.println(point.getThis().getClass()); //代理對象*/
        try {
            //開啓事務
            begin();
            //這裏執行我們自己的代碼
            point.proceed();
            //提交事務
            commit();
        } catch (Throwable throwable) {
            //回滾
            rollback(throwable);
            throwable.printStackTrace();
        }finally {
            //關閉
            close();
        }
    }


}

然後進行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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="myBeanService" class="com.ifueen._05xmlaop.service.impl.MyBeanServiceImpl"></bean>
    <bean id="txManager" class="com.ifueen._05xmlaop.TxManager"></bean>

    <!-- 配置AOP -->
    <aop:config>
        <!--
        id:切點的名稱
        execution是一個表達式,去執行方法
        *:代表任意返回值
        com.ifueen._05xmlaop.service:對應的包
        I*Service:對應的類
        *:所有的方法
        (..):方法裏面任意參數
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.ifueen._05xmlaop.service.I*Service.*(..))"/>

        <aop:aspect ref="txManager">
            <!-- 前置通知 -->
            <!--<aop:before method="begin" pointcut-ref="pointcut"></aop:before>-->
            <!-- 後置通知 -->
            <!--<aop:after-returning method="commit" pointcut-ref="pointcut"></aop:after-returning>-->
            <!-- 異常通知,如果要抓取異常的話需要在這裏也要設置 -->
            <!--<aop:after-throwing method="rollback" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>-->
            <!-- 最終通知 -->
            <!--<aop:after method="close" pointcut-ref="pointcut"></aop:after>-->
            <!-- 環繞通知 裏面可以自定義-->
            <aop:around method="around" pointcut-ref="pointcut"></aop:around>
        </aop:aspect>
    </aop:config>


</beans>

使用註解配置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: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
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 掃描包路徑 -->
    <context:component-scan base-package="com.ifueen._06annoaop"></context:component-scan>
    <!-- 支持AOP註解 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

自定義的事務類

package com.ifueen._06annoaop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 註解實現的事務
 */
@Component
@Aspect  //AOP的類註解
public class TxManager {

    //設置切點
    @Pointcut("execution(* com.ifueen._06annoaop.service.I*Service.*(..))")
    public void pointcut(){}

    //前置通知
    /*@Before("pointcut()")*/
    public void begin(){
        System.out.println("開啓事務");
    }
    //後置通知
    /*@AfterReturning("pointcut()")*/
    public void commit(){
        System.out.println("提交事務");
    }
    //異常通知
    /*@AfterThrowing(pointcut = "pointcut()",throwing = "e")*/
    public void rollback(Throwable e){
        System.out.println("回滾事務,異常的原因爲"+e.getMessage());
    }
    //最終通知
    /*@After("pointcut()")*/
    public void close(){
        System.out.println("關閉資源");
    }

    //如果要使用環繞通知,需關閉前面的註解,不然可能引起衝突
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point){
        Object object = null;
        try {
            //開啓事務
            begin();
            //這裏執行我們自己的代碼
            object = point.proceed();
            //提交事務
            commit();
        } catch (Throwable throwable) {
            //回滾
            rollback(throwable);
            throwable.printStackTrace();
        }finally {
            //關閉
            close();
        }
        return object;
    }


}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章