国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Java學習】 Spring的基礎理解 IOC、AOP以及事務

這篇具有很好參考價值的文章主要介紹了【Java學習】 Spring的基礎理解 IOC、AOP以及事務。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、簡介

? ? 官網(wǎng):?https://spring.io/projects/spring-framework#overview
? ??官方下載工具:?https://repo.spring.io/release/org/springframework/spring/
? ? github下載:?https://github.com/spring-projects/spring-framework
?? ?maven依賴:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

  1.spring全家桶的結構構圖:

?? ??? ?
? ? 最下邊的是測試單元? ?其中spring封裝了自己的測試單元
  1. ?Core Container

?? ?上邊一層(Core Container)是核心容器,也是spring框架的基礎 也是核心
  • core:提供了框架的基本組成部分? 包括ioc和依賴注入功能
  • beans:提供了BeanFactory? 實現(xiàn)了工廠模式。方便解耦
  • context:上下文內(nèi)容
  • expression:提供了強大的表達式語言,用于在運行時查詢和操作對象。

? ? 3.Data Access/Integration 數(shù)據(jù)訪問/集成

  • 該模塊包含JDBC、ORM、OXM、JMS和事務處理模塊
  • JDBC:提供了JDBC的抽象層,可以更方便的處理數(shù)據(jù)庫
  • ORM:模塊提供了流行的對象關系型映射的API的集成
  • OXM:模塊提供了對OXM實現(xiàn)的支持(啥是OXM)
  • JMS:包含了生產(chǎn)和消費消息的功能
  • 事務:毋庸置疑,可以實現(xiàn)特殊接口類以及所有的pojo支持編程式和聲明式事務管理。

?? ? 4.Web

?? ??? ?? ? Web層由Web、Servlet、Web-Sockethe和Web-Portlet組成
  • Web模塊:提供面向web的基本功能和面向web的應用上下文
  • Servlet模塊:為web應用提供了模型視圖看著(MVC)和RestWeb服務的實現(xiàn)。Spring的MVC框架可以將代碼與web表單進行分離。
  • Web-Socket
  • Web-Portlet
? ? 5.AOP
?? ??? ?? ? Aop模塊提供了面向切面編程的實現(xiàn),允許自定義放啊攔截器和切入點,對代碼繼續(xù)寧解耦,可以減少模塊間的耦合度,方便擴展和提高可維護性
? ? 6.Instrumentation
? ? 7.Messaging
? ? 8.Aspects
?? ??? ?? ? 也是面向切面編程
? ? 9.Test

二、IOC:

? 2.1理論:IOC也就是控制反轉
?? ??? ?? ? 其基本理解就是Spring將創(chuàng)建對象的過程轉交給了IOC容器。,在其它類中我們只需要調用即可,不需要重新創(chuàng)建對象。
?? ?? ? 在我們傳統(tǒng)的三層架構模型中,目錄結構分別為pojo、dao、和service
? ? 當我們在service中調用dao時,常會使用到
?? ??? ?private UserDao userDao=new UserDao();
? ? 這就是我們通常的思維,需要創(chuàng)建對象才可以使用,但是引入spring后,便可以使用<bean>標簽就可以創(chuàng)建對象。
? ? 2.2 Spring 中IOC的實現(xiàn)提供了兩種方式:
?? ?? ? 2.2.1BeanFactory:這是IOC的基本實現(xiàn),是Spring的內(nèi)部接口,不會提供給開發(fā)人員使用。
?? ?? ? 加載配置文件時,不會創(chuàng)建對象,只有在使用的時候才會創(chuàng)建對象(一會可以代碼解釋? 注意的是getBean的動作)
?? ?? ? 2.2.2ApplicationContext 它是BeanFactory接口的子接口,提供了更加強大的功能開發(fā)人員進行加載配置文件的時候就進行了創(chuàng)建。
//1.引入jar包

//2.編輯配置文件
<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
配置對象  id為唯一限定名 一般為類名的小寫   class是類所在的位置
    <bean id="teacher" class="com.qiang.pojo.Teacher"></bean>
</beans>

//3.測試
@Test
public void testTeacherCreate(){
    //加載配置文件
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
    Teacher teacher = ac.getBean("teacher", Teacher.class);
    System.out.println(teacher);
}

//在以上代碼中  如果使用的是ApplicationContext 則在進行加載配置文件時 就已經(jīng)在IOC容器中創(chuàng)建好了teacher對象
//如果是使用的是 BeanFactory ac 創(chuàng)建對象,則在getbean時才會創(chuàng)建對象(不可操作,因為該接口不對開發(fā)人員透明)

2.2.3 ApplicationContext接口的實現(xiàn)類的繼承關系

【Java學習】 Spring的基礎理解 IOC、AOP以及事務

由上圖可以看出,我們能使用的只有ClassPathXMlApplicationContext和FileSystemXmlApplicationContext來解析我們的xml配置文件。
其中Class開頭的可以去classpath路徑下去尋找
File開頭的可以加載磁盤路徑下的配置文件
之后我們還可以使用AnnotationconfigApplicationContext可以使用注解方式來創(chuàng)建容器。
?
2.3 IOC對Bean的管理
? ? 2.3.1 創(chuàng)建bean
?? ?? ? bean就是我們所說的Java對象,在之前所學的創(chuàng)建Java對象,一般是使用new關鍵字 調用類中的構造器來創(chuàng)建對象。
? ? 因此創(chuàng)建bean的方法就可以有三種方式:使用默認的無參構造、使用簡單工廠方式創(chuàng)建、使用靜態(tài)工廠方式創(chuàng)建
?? ?? ? A:使用默認的無參構造
<bean id="唯一標識" class="類的全限定名"> </bean>

? ? ? ? B :使用普通工廠類創(chuàng)建bean實例

1.建立普通類teacher,包含個別屬性,并添加get、set方法

2.創(chuàng)建工廠類
public class SchoolFactory {
    Teacher teacher=new Teacher();
    public  Teacher getInstance(){
        return teacher;
    }
}
在工廠類中實例化對象,并添加一個普通方法可以獲取到對象

3.配置文件

<!--    普通工廠類創(chuàng)建bean實例-->
    <bean id="factory" class="com.qiang.pojo.factory.SchoolFactory" ></bean>
    <bean id="teacher1" factory-bean="factory" factory-method="getInstance"></bean>

第一個bean是一個實例化的對象也就是對象工廠
第二個bean 是利用對象工廠來創(chuàng)建的對象實例化
            factory標簽指的是  是哪個工廠對象,對應上邊的id
            factory-method指的是調用可以獲取對象實例的方法(普通方法)


4.測試:

/**
* 測試普通工廠類創(chuàng)建bean實例
*/
@Test
public void testTeacherFactory1(){
    //加載配置文件
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
    Teacher teacher1 = ac.getBean("teacher1", Teacher.class);
    System.out.println(teacher1);
}

如果在程序中可能需要頻繁的創(chuàng)建某個類的實例對象,采用工廠模式會更好

? 2.3.2 依賴注入 也就是注入屬性
?
?? ??? ?? ? 依賴注入也就是對屬性的注入,分為三種:構造器注入、set注入以及p標簽注入
?? ??? ?? ? 其中的構造注入,需要走的是帶參構造
?? ??? ?? ? set注入,走的是set方法和無參構造
?? ??? ?? ? p標簽注入和set注入基本一樣,只不過頭文件中需要引入
?
?? ??? ?對象工廠接口中最基本的是BeanFactory,它可以支持懶加載,也就是在加載配置文件時,不會創(chuàng)建實例對象,而是在需要調用時才會創(chuàng)建。
?? ?? ? 如今使用的是applicationContext來解析配置文件,他的底層接口也是BeanFactory,但是它可以在加載配置文件的時候,就直接創(chuàng)建了bean實例。
?
?
?? ?? ? 以Student類作為演示
public class Student {
    private String sname;
    private int age;
    private String sex;


    public Student(String sname, int age, String sex) {
        this.sname = sname;
        this.age = age;
        this.sex = sex;
        System.out.println("這是三個參數(shù)的無參構造");
    }


    public Student(String sname, int age) {
        this.sname = sname;
        this.age = age;
        System.out.println("這是第一個屬性為name的兩個參數(shù)的構造");
    }
    public Student( int age,String sname) {
        this.sname = sname;
        this.age = age;
        System.out.println("這是第一個屬性為age的兩個參數(shù)的構造");


    }


    public Student() {
        System.out.println("這是無參構造");
    }




    public String getSname() {
        return sname;
    }


    public void setSname(String sname) {
        this.sname = sname;
    }


    public int getAge() {
        return age;
    }


    public void setAge(int age) {
        this.age = age;
    }


    public String getSex() {
        return sex;
    }


    public void setSex(String sex) {
        this.sex = sex;
    }


    @Override
    public String toString() {
        return "Student{" +
                "sname='" + sname + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}
  A 構造器注入 <constructor-arg>
<bean id="stu1" class="com.qiang.pojo.Student">
    <constructor-arg name="sname" value="zs"></constructor-arg>
    <constructor-arg name="age" value="15"></constructor-arg>
</bean>
看我們的實體類中就可以發(fā)現(xiàn),我們的含有兩個參數(shù)的構造器,有兩個,在這個時候我們使用的構造器的構造函數(shù)就不知道使用的是哪個帶參的構造器
因此我們可以使用 index來標識下標 就可以指定先執(zhí)行那個代餐的構造

    其中constructor-arg中也可以使用type來標識參數(shù)類型來確定屬性
        如果是八大基本數(shù)據(jù)類型,則可以直接寫關鍵字,如果是其他類型,則需要添加類的全限定路徑

    如果其中還含有其他對象類型的參數(shù),
    如此時的student類中包含屬性  private Grade grade;
    
    構造器:
        <bean>
        <construct-arg type="com.qiang.Grade" ref="grade"></construct-arg>
        </bean>
            
        <bean id="grade" class="com.qiang.Grade"></bean>

  ?B set方法注入? 此時需要在類中對屬性添加set方法 以及無參構造

<bean id="student2" class="com.qiang.pojo.Student">
        <property name="id" value="2"></property>
        <property name="name" value="李四"></property>
    </bean>

  ? C :p標簽注入 此時就要添加對應的set方法以及無參構造 以及添加頭文件

  ? D:也可以set注入和構造器注入 混合使用 但是需要有對應的構造方法

? 2.3.3? ?不同屬性類型對應的寫法:
?? ?? ? 由于我們的屬性的在不同的使用場景下可能有不同的屬性類型,如集合、數(shù)組等情況,因此可能會需要使用到不同的標簽,下面只演示使用set方法注入的情況 那就意味著,我們需要添加構造方法和無參構造。
實體類
public class Order {
    private String [] cources;
    private List<String> lists;
    private Map<String,String> maps;
    private Set<String> sets;
配置文件

<!--    測試不同屬性類型的屬性注入-->
    <bean id="order" class="com.qiang.pojo.Order">
<!--        數(shù)組集合使用array標簽-->
        <property name="cources">
            <array>
                <value>美羊羊</value>
                <value>蘭羊羊</value>
            </array>
        </property>
<!--        list集合類型使用list標簽-->
        <property name="lists">
            <list>
                <value>舒克</value>
                <value>貝塔</value>
            </list>
        </property>
<!--        set集合使用set標簽-->
        <property name="sets">
            <set>
                <value>mysql</value>
                <value>javase</value>
                <value>javaweb</value>
            </set>
        </property>


        <property name="maps">
            <map>
                <entry key="java" value="我們在學習的語言"></entry>
                <entry key="web" value="前端的"></entry>
            </map>
        </property>
數(shù)組類型的使用<array><value></value></array>
? ? list類表類型的使用:<list><value></value></list>
?? ?set集合類型的使用<set><value></value></set>
? ? map集合類型的使用<map><entry key="" value=""></entry></map>
?
2.4 Bean的作用域: scope屬性
  • singleton:默認值? 單例模式 每次獲取的bean都是同一個對象
  • prototype:每次獲取bean都會被重新實例化
  • request:每次請求都會重新實例化對象,但是在同一請求下獲取的情況下的bean是單例的
  • session? 每次會話內(nèi)的bean是單例的
  • application:整個應用程序對象內(nèi)的bean實例都是單例模式的
  • websocket:同一個websocket對象內(nèi)的對象是單例的。
Singleton
<!--    測試單例模式-->
    <bean id="stu3" class="com.qiang.pojo.Student" scope="singleton"></bean>

測試類:

@Test
public void testStudent3(){
    //加載配置文件
    BeanFactory ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
    Student stu1 = ac.getBean("stu3", Student.class);
    System.out.println(stu1);
    Student stu2 = ac.getBean("stu3", Student.class);
    System.out.println(stu2);
    System.out.println(stu1==stu2);
}

結果:
com.qiang.pojo.Student@10a035a0
com.qiang.pojo.Student@10a035a0
true
prototype

<!--    測試多例模式-->
<bean id="stu4" class="com.qiang.pojo.Student" scope="prototype"></bean>

測試類

@Test
public void testStudent4(){
    //加載配置文件
    BeanFactory ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
    Student stu1 = ac.getBean("stu4", Student.class);
    System.out.println(stu1);
    Student stu2 = ac.getBean("stu4", Student.class);
    System.out.println(stu2);
    System.out.println(stu1==stu2);
}

結果:
com.qiang.pojo.Student@10a035a0
com.qiang.pojo.Student@67b467e9
false
2.5? bean的生命周期
? ? ?2.5.1 一般理解下的bean的生命周期:
  • 通過構造器創(chuàng)建bean實【此時執(zhí)行的是無參構造】
  • 為bean屬性設置值以及對其他的bean的引用【set注入】
  • 調用bean的初始化方法,在配置文件中配置
  • bean對象可以使用了 【已經(jīng)獲取到了對象】
  • 當容器關閉時,調用bean的銷毀方法【在配置文件中配置】
實體類對象
public class People implements Serializable {
    private String oid;
    public People() {
        System.out.println("第一步:執(zhí)行無參構造");
    }
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
        System.out.println("第二步: 調用set方法給屬性設置值......");
    }
    public void initMethod(){
        System.out.println("第三步:執(zhí)行初始化方法............");
    }
    public void destroyMethod(){
        System.out.println("第五步:執(zhí)行銷毀方法............");
    }
    @Override
    public String toString() {
        return "People{" +
                "oid='" + oid + '\'' +
                '}';
    }
}
配置文件  添加初始化方法 和銷毀方法
<bean id="people" class="com.qiang.pojo.People" 
    init-method="initMethod" 
    destroy-method="destroyMethod">
</bean>
其中的標簽init-method、destroy-method 中的方法是在實體類中自定義的

 測試類

/**
* 測試bean的生命周期
*/
@Test
public void testBeanLive(){
    //加載配置文件
    ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
    //獲取bean實例
    People people = ac.getBean("people", People.class);
    System.out.println("第四步:獲取bean實例對象 。。。");
    System.out.println(people);
    //手動銷毀
    ac.close();
}



結果:
第一步:執(zhí)行無參構造
第三步:執(zhí)行初始化方法............
第四步:獲取bean實例對象 。。。
People{oid='null'}
第五步:執(zhí)行銷毀方法............

?文章來源地址http://www.zghlxwxcb.cn/news/detail-488611.html

? 2.5.2 添加后置處理器的生命周期的方法
  • 第一步:執(zhí)行無參數(shù)的構造方法 。。。
  • 第二步: 調用set方法給屬性設置值......
  • 在初始化之前執(zhí)行的方法
  • 第三步:執(zhí)行初始化方法............
  • 在初始化之后執(zhí)行的方法
  • 第四步:獲取bean實例對象 。。。
  • 第五步:執(zhí)行銷毀方法............

?

在實體類中 實現(xiàn)了BeanPostProcessor接口
    并重寫了
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("在初始化之前執(zhí)行的方法");
    return bean;
}


@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("在初始化之后執(zhí)行的方法");


    return bean;
}

?

? 2.6 自動裝配:
? ? 裝配的意思是 就是怎么去創(chuàng)建對象
spring的裝配方式有三種:
?? ?? ? 在xml中顯示的裝配 也就是使用<bean>標簽
?? ?? ? 在Java中的顯示配置 new關鍵字
?? ?? ? 自動裝配機制
?
?? ?? ? Spring的自動裝配你有兩個角度的實現(xiàn)
?? ??? ?? ? 分別是 組件掃描和 自動裝配
?? ??? ??? ?? ? 組件掃描:spring 回自動發(fā)現(xiàn)應用上下文中所創(chuàng)建的bean
?? ??? ??? ?? ? 自動裝配:spring自動滿足bean之間的依賴,也就是使用IOC和DI
?? ? 自動裝配的實現(xiàn)方式有兩種,一種是通過xml的bena標簽 也可以使用注解方式
?? ?? ? 2.6.1? 通過XMl中的標簽 自動裝配
?? ?
? ? A:byName 按名稱自動裝配
?? ?? ? 通俗理解:在xml配置文件中 使用bean標簽 通過bynae自動諸如和,每次遇到名稱為 byname屬性值時就自動創(chuàng)建對象
實體類Dog
private String color;
private int age;


配置文件
<bean id="d1" class="com.qiang.pojo.Dog" autowire="byName">
    <property name="age" value="15"></property>
</bean>

測試類:
@Test
public void testDog1(){
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
    Dog d1 = ac.getBean("d1", Dog.class);
    System.out.println(d1.getAge());
}

結果:
15

  B.byType 按類型自動裝配

配置文件
<bean id="d1" class="com.qiang.pojo.Dog" autowire="byType">
    <property name="age" value="21"></property>
</bean>


測試類:
@Test
public void testDog1(){
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
    Dog d1 = ac.getBean(Dog.class);
    System.out.println(d1.getAge());
}


結果:
21

?

2.6.2根據(jù)注解開發(fā)
?? ??? ?? ? spring中的注解注入的有:@Autowired、@Resources @Qualifier? ?@Service @Commonent @Controller? @Repository
? ? 在使用注解開發(fā)時,需要現(xiàn)在配置文件中開啟組件掃描功能
<!--開啟組件掃描-->
????<context:component-scan base-package="cn.liushao"></context:component-scan>
?
開啟組件掃描? 便可以自動查找其中的自動注入
? ? 不同的注解的區(qū)分:
  • Autowired是自動注入,自動從spring的上下文找到合適的bean來注入。
  • Resource用來指定名稱注入。
  • Qualifier和Autowired配合使用,指定bean的名稱。
  • Service,Controller,Repository分別標記類是Service層類,Controller層類,Dao層的類,spring掃描注解配置時,會標記這些類要生成bean。
  • Component是一種泛指,標記類是組件,spring掃描注解配置時,會標記這些類要生成bean。
@Autowired注解
? ? 默認按類型裝配springbean 默認情況下,必須要求依賴對象必須存在。如果容器中有多個相同類型的bean,則框架會拋出異常。
? ? @Qualifier
? ? 此注解用來消除依賴注入沖突的。我們可以消除需要注入那個bean的問題
? ? 通過該注解,我們可以使用特定的Spring Bean一起裝配,Spring框架可以從多個相同類型并滿足裝配要求的bean中找到我們想要的。
? ? @Resource是按名稱裝配:

?

分析:  由于注解@Autowired是默認按類型裝配的,一個類型的可能會有多個實現(xiàn)方法
        因此在演示的時候 就可以選擇一個接口,有多個實現(xiàn)類來作為演示

1.構建一個接口
public interface TeacherService {
    public void sayName();
    public void saysex();
}


2.創(chuàng)建多個實現(xiàn)類(以三個舉例)
@Component
public class TeacherServiceImpl1 implements TeacherService {
    @Override
    public void sayName() {
        System.out.println("A");
    }
}

@Component
public class TeacherServiceImpl1 implements TeacherService {
    @Override
    public void sayName() {
        System.out.println("B");
    }
}

@Component
public class TeacherServiceImpl1 implements TeacherService {
    @Override
    public void sayName() {
        System.out.println("C");
    }
}

3.創(chuàng)建兩外一個類,可以調用該類的實現(xiàn)類
public class TeacherController {
    @Autowired
    //創(chuàng)建對象
    private TeacherService teacherService;
    public void soutResult(){
        teacherService.sayName();
    }
}

4.修改配置文件 開啟掃描

<!--    測試注解開發(fā)-->
    <context:component-scan base-package="com.qiang"></context:component-scan>

5.測試:

@Test
public void testAopAno(){
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
    TeacherController contro = ac.getBean("teacherController", TeacherController.class);
    contro.soutResult();
}
6.觀察結果:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'teacherController': Unsatisfied dependency expressed through field 'teacherService'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.qiang.service.TeacherService' available: expected single matching bean but found 3: teacherServiceImpl1,teacherServiceImpl2,teacherServiceImpl3

分析:由于在service接口有多個實現(xiàn)類,使用autowired是按類型注入,可能會找不到使用哪個  因此可以搭配使用@Qualifier注解


修改第三步:
public class TeacherController {
    @Autowired
    @Qualifier("teacherServiceImpl1")
    //創(chuàng)建對象
    private TeacherService teacherService;
    public void soutResult(){
        teacherService.sayName();
    }
}
繼續(xù)進行測試  結果為:
A
結果顯示正常


繼續(xù)修改第三步:
public class TeacherController {
   @Resource(name = "teacherServiceImpl1")
    //創(chuàng)建對象
    private TeacherService teacherService;
    public void soutResult(){
        teacherService.sayName();
    }
}
繼續(xù)進行測試  結果為:
A
結果顯示正常

?

通過上述例子可以看出,如果一個類需要由多個實例變量時,可以搭配使用?@Autowired
?? ?@Qualifier("teacherServiceImpl1"),也可以單獨使用?@Resource(name = "teacherServiceImpl1"

?

三、AOP
?
? ? 3.1AOP簡介:
?? ?? ? AOP通俗理解就是面向切面編程,是對面向對象的一種補充、將那些與業(yè)務無關的,但卻對多個對象產(chǎn)生影響的公共行為和邏輯,抽取并封裝為一個可重用的模板,這個模板就被稱為”切面“,使用AOP減少了系統(tǒng)中的重復代碼、降低了模塊間的耦合度,同時提高了系統(tǒng)的可維護性。
? ? AOP的底層是動態(tài)代理,分別為JDK動態(tài)代理和CGLIB動態(tài)代理
?
? ? 3.2術語:
?? ?? ? 連接點:可以被增強的方法
?? ??? ?
?? ??? ?切入點:?實際真正被增強的方法,稱為切入點
?
?? ??? ?通知(增強):又被叫做增強,實際增強的邏輯部分稱為通知[增強]
?
?? ?? ? 切面(是個動作):把通知應用到切入點的過程。
?
其中:通知有五種:
?? ?? ? 前置通知(before) 后置(返回)通知(after returning) 、環(huán)繞通知(Around)、異常通知(after-throwing)
?
通知通俗理解就是AOP暴漏給我們的方法,我們在這個方法中直接定義需要擴展的代碼即可,但是其執(zhí)行順序,交給了spring來處理。
?
?
?? ?? ? 3.3 AOP的準備工作:
首先介紹一下Aspect J  這個是一個獨立的AOP模型,但不是Spring框架的內(nèi)容。
? ? 因此在演示的時候需要導入相關的jar包,或者使用maven文件
?
?
? ? 切入點表達式:知道對那個類的方法進行增強
?? ?? ? execution( [權限修飾符] [返回值類型] [類的全路徑] [方法名][參數(shù)列表])
?
? ? 3.4 AOP通知
?? ?? ? 3.4.1基于XML的配置通知
? ? A 第一種方式:
1.添加jar包

2.建造實體類和代理對象類
    普通類應包含一個普通方法,該普通方法也就是要增強的那個方法
public class Student implements Serializable {
    public void add(){
        System.out.println("這個只是一個普通的方法");
    }
}


public class StudentProxy {
    //配置前置通知
    public void before(){
        System.out.println("前置通知。。。。。");
    }
    //配置后置返回通知
    public void afterreturning(){
        System.out.println("后置返回通知....");
    }
    //配置最終通知
    public void after(){
        System.out.println("最終通知....");
    }
    //配置環(huán)繞通知
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("環(huán)繞通知前");
        proceedingJoinPoint.proceed();
        System.out.println("環(huán)繞通知后....");
    }
    //配置異常通知
    public void afterThrow(){
        System.out.println("異常通知....");
    }
}



3.修改配置文件


在修改配置文件時應注意,頭文件也需要進行修改

xmlns:aop="http://www.springframework.org/schema/aop"
xsi:http://www.springframework.org/schema/aop
    https://www.springframework.org/schema/aop/spring-aop.xsd"

//注入
<bean id="student" class="com.qiang.pojo.Student"></bean>
<bean id="studentProxy" class="com.qiang.pojo.StudentProxy"></bean>

<aop:config >
    <!--切入點-->
    <aop:pointcut id="pc" expression="execution(* com.qiang.pojo.Student.add(..))"/>
    <!--配置切面-->
    <aop:aspect ref="studentProxy">
        <!--將增強應用到具體的方法上-->
        <!--前置通知-->
        <aop:before method="before" pointcut-ref="pc"></aop:before>
        <!--后置返回通知-->
       <aop:after-returning method="afterreturning" pointcut-ref="pc"></aop:after-returning>
        <!--最終通知-->
        <aop:after method="after" pointcut-ref="pc"></aop:after>
        <!--環(huán)繞通知-->
        <aop:around method="around" pointcut-ref="pc"></aop:around>
    </aop:aspect>
以上沒有演示異常通知,異常通知在程序發(fā)生異常時才會發(fā)生。


測試:
@Test
public void testAopXmlDemo1(){
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig.xml");
    Student student = ac.getBean("student", Student.class);
    student.add();
}



結果:

前置通知。。。。。
環(huán)繞通知前
這個只是一個普通的方法
環(huán)繞通知后....
最終通知....
后置返回通知....
分析:
? ? 前置通知:在連接點之前執(zhí)行的通知
? ? 后置返回通知:一般在方法的結尾,必然會多一個返回值
? ? 環(huán)繞通知:包含了前置通知和后置通知
? ? 異常通知:處理異常數(shù)據(jù),事務回滾
? ??
3.4.2基于注解的配置通知
? ? B:第二種方式
1.引入jar包
 
2.創(chuàng)建實體類
@Component
public class User {
    public void add(){
        System.out.println("這是一個普通方法");
    }
}

3.創(chuàng)建代理類
@Component
@Aspect //生成代理對象
public class UserProxy {
    //前置通知
    @Before(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
    public void before(){
        System.out.println("前置通知。。。");
    }
    //后置返回通知
    @AfterReturning(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
    public void afterReturning(){
        System.out.println("后置返回通知afterReturning....");
    }
    //環(huán)繞通知
    @Around(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("環(huán)繞之前....");
        // 被增強的方法執(zhí)行了
        proceedingJoinPoint.proceed();
        System.out.println("環(huán)繞之后....");
    }
//    //異常通知 只有手動創(chuàng)造了異常才可以觸發(fā)這個通知
//    @AfterThrowing(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
//    public void afterThrowing(){
//        System.out.println("異常通知 afterThrowing......");
//    }


//最終通知
    @After(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
    public void after(){
        System.out.println("最終通知....");
    }

}

//修改配置文件


<!--    開啟組件掃描-->
    <context:component-scan base-package="org.qiang.aop.anno"></context:component-scan>


<!--    開啟Aspect生成代理對象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>


//測試:

@Test
public void testAopAnno(){
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationConfig2.xml");
    User user = ac.getBean("user", User.class);
    user.add();
}



結果:
環(huán)繞之前....
前置通知。。。
這是一個普通方法
環(huán)繞之后....
最終通知....
后置返回通知afterReturning....

? ? C:第三種方式抽取重復代碼

只需要修改代理類對象就可以了
@Component
@Aspect //生成代理對象
public class UserProxy {




//    抽取切入點
    @Pointcut(value = "execution(* org.qiang.aop.anno.pojo.User.add(..))")
    public void pointcutDemo(){


    }
    //前置通知
    @Before(value = "pointcutDemo()")
    public void before(){
        System.out.println("前置通知。。。");
    }
   
   
    //后置返回通知
    @AfterReturning(value = "pointcutDemo()")
    public void afterReturning(){
        System.out.println("后置返回通知afterReturning....");
    }
   
   
    //環(huán)繞通知
    @Around(value = "pointcutDemo()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("環(huán)繞之前....");
        // 被增強的方法執(zhí)行了
        proceedingJoinPoint.proceed();
        System.out.println("環(huán)繞之后....");
    }
    
    
//    //異常通知 只有手動創(chuàng)造了異常才可以觸發(fā)這個通知
//    @AfterThrowing(value = "pointcutDemo()")
//    public void afterThrowing(){
//        System.out.println("異常通知 afterThrowing......");
//    }


    
    
    //最終通知
    @After(value = "pointcutDemo()")
    public void after(){
        System.out.println("最終通知....");
    }
    
}
? D :? AOP 底層是動態(tài)代理默認的是JDK動態(tài)代理的方法,也可以通過
?? ?<aop: aspectj-autoproxy proxy-target-class="true"></aop :aspect-autoproxy>
標簽來修改,其默認值是false是JDK動態(tài)代理的格式,改為true就可以使用CGLIB代理格式。

?

3.5 Spring的事務管理
?
? ? Spring框架將固定的冗余部分的套路代碼進行了封裝,對程序員僅提供簡單的XML配置就可以完成事務的管理,不需要在編寫事務管理代碼。這也就是Spring的非常重要功能--聲明式事務
?? ?
? ? 聲明式事務是基于AOP實現(xiàn)的(動態(tài)代理)。程序員只需要調用持久層代碼和業(yè)務邏輯代碼,將開啟事務的代碼反正該了前置通知中,將事務回滾和事務提交的代碼放在了后置通知中。
?
?
? ? 使用事物可以保證操作前后數(shù)據(jù)的完整性,事務的四個特性:ACID 原子性、一致性、隔離性和持久性
?
?
? ? 編程式事務:整個事務的操作都是由程序員進行手動管理,手動提交,手動回滾
? ? 聲明式事務:整個事務由其他框架進行管理,我們使用事務的時候只需要進行簡單的聲明或
?? ??? ??? ??? ??? ??? ?者配置即可。
?
?
? ? Spring中的Tx模塊就包含了對聲明式事務的封裝,以下是我們的日常的手動提交事務的寫法:
public void testdemo1() throws SQLException {
    Connection conn= DriverManager.getConnection("","","");
    //關閉自動提交
    conn.setAutoCommit(false);
    try {
        PreparedStatement ptst=conn.prepareStatement("insert into bank  values=(?,?)");
        
        ptst.executeUpdate();
        
    }catch (Exception e){
    //再發(fā)生異常時,就會進行事務的回滾
        conn.rollback();
    }
    
}
? ?回顧Aop切面編程,可以發(fā)現(xiàn)共通點,在關閉自動提交的部分,可以用前置通知來代替,try代碼塊的部分就可以理解為是切入點,事務提交的部分可以使用后置通知來實現(xiàn),而對于出現(xiàn)異常,事務回滾的操作就可以使用異常通知來處理。
也就是:
在org.springframework.jdbc.datasource.DataSourceTransactionManager 中的
方法:
protected void doBegin(){
    conn.setAutoCommit(false)
}

protected void doBegin() {

}

protected void doRollback() {


}

?

添加事務通知:

<tx:advice id="tt" transaction-manager="transactionmanager">
    <tx:attributes>
            <tx: method name="方法名">
    </tx:attributes>
</ tx: advice>


<aop:config>
              <aop:pointcut id="pt"  expression="execution(* 類的全路徑.方法(. .))" />
            <aop:advisor advice-ref="tt"  pointcut-ref="pt"> </aop:advisor>
</aop:config>

?

?

聲明式事務的四個基礎屬性介紹:
?? ?? ? <tx:method>標簽下有屬性配置,也可以用在注解上:

?

?

?

?

?

?

?

?

到了這里,關于【Java學習】 Spring的基礎理解 IOC、AOP以及事務的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Spring IOC 與 AOP 基礎原理,一篇搞定

    控制反轉,一切對象交給Spring來創(chuàng)建于管理,將創(chuàng)建與使用對象的代碼進行分離作用。實現(xiàn)代碼的解耦。 因為以前的對象創(chuàng)建都是在程序的創(chuàng)建,管理。這是所謂的正轉,如今的對象的創(chuàng)建是在IOC中,在 IOC Container中獲取。這就是反轉。 DI,denpendecy inject。依賴注入,在應用

    2024年01月21日
    瀏覽(17)
  • 【Java面試】Spring中的IOC和AOP

    IOC:控制反轉也叫依賴注入。利用了工廠模式 將對象交給容器管理,你只需要在spring配置文件總配置相應的bean,以及設置相關的屬性,讓spring容器來生成類的實例對象以及管理對象。在spring容器啟動的時候,spring會把你在配置文件中配置的bean都初始化好,然后在你需要調用的

    2024年02月10日
    瀏覽(26)
  • IDEA項目實踐——Spring框架簡介,以及IOC注解

    IDEA項目實踐——Spring框架簡介,以及IOC注解

    IDEA創(chuàng)建項目的操作步驟以及在虛擬機里面創(chuàng)建Scala的項目簡單介紹 IDEA項目實踐——創(chuàng)建Java項目以及創(chuàng)建Maven項目案例、使用數(shù)據(jù)庫連接池創(chuàng)建項目簡介 IDEWA項目實踐——mybatis的一些基本原理以及案例 IDEA項目實踐——動態(tài)SQL、關系映射、注解開發(fā) 文章目錄 第1章 Spring 概述

    2024年02月14日
    瀏覽(20)
  • 深入了解 Spring boot的事務管理機制:掌握 Spring 事務的幾種傳播行為、隔離級別和回滾機制,理解 AOP 在事務管理中的應用

    深入了解 Spring boot的事務管理機制:掌握 Spring 事務的幾種傳播行為、隔離級別和回滾機制,理解 AOP 在事務管理中的應用

    ????歡迎光臨,終于等到你啦???? ??我是蘇澤,一位對技術充滿熱情的探索者和分享者。???? ??持續(xù)更新的專欄 《Spring 狂野之旅:從入門到入魔》 ?? 本專欄帶你從Spring入門到入魔 ? 這是蘇澤的個人主頁可以看到我其他的內(nèi)容哦???? 努力的蘇澤 http://suzee.blog.csdn

    2024年03月21日
    瀏覽(24)
  • 【面試題】談談你對IOC和AOP的理解

    IoC(Inverse of Control:控制反轉)是一種設計思想,就是將 原本在程序中手動創(chuàng)建對象的控制權,交由Spring框架來管理 。IOC思想是基于IOC容器來完成的,IOC容器底層就是對象工廠(BeanFactory接口)。IOC的原理是基于xml解析、工廠設計模式、反射來實現(xiàn)的。?IoC 容器實際上就是個

    2024年02月05日
    瀏覽(18)
  • Spring IOC & AOP

    Spring IOC & AOP

    IOC,全程Inversion of Control(控制反轉) 通過控制反轉(創(chuàng)建對象的權限交給框架,所以叫反轉)創(chuàng)建的對象被稱為 Spring Bean ,這個Bean和用new創(chuàng)建出來的對象是沒有任何區(qū)別的。 官方解釋:Spring 通過 IoC 容器來管理所有 Java 對象的實例化和初始化,控制對象與對象之間的依賴

    2024年02月16日
    瀏覽(20)
  • spring的AOP和IOC的原理

    spring的AOP和IOC的原理

    目錄 一、spring的ioc與aop原理 二、代理模式: 三、靜態(tài)代理 四、動態(tài)代理 五、實際的操作 六、動態(tài)代理的實現(xiàn): 七、什么是AOP 八、主流的AOP框架: 九、術語: 十、通知的五種類型: 十一、AOP的優(yōu)點: 十二、AOP開發(fā)流程 核心概念:控制反轉(IOC)/(DI),面向切面(AO

    2024年02月05日
    瀏覽(32)
  • Spring核心思想之IOC和AOP

    Spring核心思想之IOC和AOP

    IOC和AOP不是Spring提出的,在spring之前就已經(jīng)存在,只不過更偏向于理論化,Spring在技術層次把這兩個思想做了?常好的實現(xiàn)(Java)。 什么是IoC? IoC Inversion of Control (控制反轉/反轉控制),注意它是?個 技術思想 ,不是?個技術實現(xiàn)。 描述的事情 :Java開發(fā)領域對象的創(chuàng)建,

    2024年02月09日
    瀏覽(22)
  • spring框架,以及和spring框架相關的Java面試題和spring ioc的注入方式

    spring框架,以及和spring框架相關的Java面試題和spring ioc的注入方式

    目錄 一.spring來源,以及介紹 1.spring誕生的背景 2.spring框架 介紹 3.spring框架在使用中的優(yōu)點以及不足 3.1優(yōu)點 ?3.2不足 3.3總結 4.為什么要使用spring? 二.將spring框架部署在IDEA中? 1.替換pom.xml ?2.構建spring所需要的xml文件 三.spring的三種注入方式 0.定義需要的類,方法 1.方法注入

    2024年02月12日
    瀏覽(19)
  • 深入解析Spring的IOC與AOP及其在項目中的應用

    在現(xiàn)代的軟件開發(fā)中,為了提高代碼的可維護性、可擴展性以及降低代碼的耦合度,使用設計模式和面向切面編程(AOP)成為了程序員們常用的技術手段。Spring作為一個優(yōu)秀的Java開發(fā)框架,提供了IOC和AOP兩個核心特性,極大地簡化了開發(fā)工作。本文將深入探討Spring的IOC和AO

    2024年02月13日
    瀏覽(35)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包