Browse Source

0427 spring aop

Qing 1 năm trước cách đây
mục cha
commit
adadf8d9fd

+ 1 - 0
spring-demo/.idea/misc.xml

@@ -7,6 +7,7 @@
         <option value="$PROJECT_DIR$/pom.xml" />
       </list>
     </option>
+    <option name="workspaceImportForciblyTurnedOn" value="true" />
   </component>
   <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />

+ 67 - 51
spring-demo/.idea/workspace.xml

@@ -4,20 +4,24 @@
     <option name="autoReloadType" value="SELECTIVE" />
   </component>
   <component name="ChangeListManager">
-    <list default="true" id="5aa6272e-23b4-48f4-9aaa-8caf45810aa0" name="Changes" comment="0420 spring ioc">
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/Client.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/GamePlayer.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/GamePlayerProxy.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/IGamePlayer.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/cglib/CglibClient.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/cglib/CglibDemo.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/cglib/MyMethodInterceptor.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/jdk/JdkClient.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/jdk/JdkDemo.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/jdk/MyInvocationHandler.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/jdk/self/$Proxy0.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/jdk/self/Life.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/proxy/jdk/self/MyLife.java" afterDir="false" />
+    <list default="true" id="5aa6272e-23b4-48f4-9aaa-8caf45810aa0" name="Changes" comment="0424 spring proxy">
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/BaseService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/MyAfterAdvice.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/MyBeforeAdvice.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/Person.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/advisor/EatMethodMatcher.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/advisor/MyClassFilter.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/advisor/MyPointCut.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/advisor/MyPointCutAdvisor.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aop/advisor/WcMethodMatcher.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aspect/Audience.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aspect/CrossTalk.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/sf/aspect/Performance.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/resources/spring-advisor.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/resources/spring-aop.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/resources/spring-aspect.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/test/java/com/sf/TestAop.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/pom.xml" beforeDir="false" afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
     </list>
@@ -36,9 +40,9 @@
       <list>
         <option value="Spring File" />
         <option value="AnnotationType" />
-        <option value="Spring Xml File" />
         <option value="Interface" />
         <option value="Class" />
+        <option value="Spring Xml File" />
       </list>
     </option>
   </component>
@@ -88,6 +92,8 @@
     "JUnit.TestAnno.executor": "Run",
     "JUnit.TestAnno.test.executor": "Run",
     "JUnit.TestAnno.testAnno.executor": "Run",
+    "JUnit.TestAop.test.executor": "Run",
+    "JUnit.TestAop.testAdvisor.executor": "Run",
     "JUnit.TestAuto.test.executor": "Run",
     "JUnit.TestConfig.test.executor": "Run",
     "JUnit.TestFactory.test.executor": "Run",
@@ -111,7 +117,7 @@
     "project.structure.last.edited": "Project",
     "project.structure.proportion": "0.1809181",
     "project.structure.side.proportion": "0.22295515",
-    "settings.editor.selected.configurable": "MavenSettings",
+    "settings.editor.selected.configurable": "preferences.pluginManager",
     "vue.rearranger.settings.migration": "true"
   }
 }]]></component>
@@ -124,28 +130,13 @@
       <recent name="com.sf.anno" />
     </key>
   </component>
-  <component name="RunManager" selected="Application.JdkDemo (1)">
-    <configuration name="CglibClient" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
-      <option name="MAIN_CLASS_NAME" value="com.sf.proxy.cglib.CglibClient" />
-      <module name="spring-demo" />
-      <option name="VM_PARAMETERS" value="--add-opens java.base/java.lang=ALL-UNNAMED" />
-      <extension name="coverage">
-        <pattern>
-          <option name="PATTERN" value="com.sf.proxy.cglib.*" />
-          <option name="ENABLED" value="true" />
-        </pattern>
-      </extension>
-      <method v="2">
-        <option name="Make" enabled="true" />
-      </method>
-    </configuration>
-    <configuration name="CglibDemo" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
-      <option name="MAIN_CLASS_NAME" value="com.sf.proxy.cglib.CglibDemo" />
+  <component name="RunManager" selected="JUnit.TestAop.testAdvisor">
+    <configuration name="JdkDemo (2)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
+      <option name="MAIN_CLASS_NAME" value="com.sf.proxy.jdk.JdkDemo" />
       <module name="spring-demo" />
-      <option name="VM_PARAMETERS" value="--add-opens java.base/java.lang=ALL-UNNAMED" />
       <extension name="coverage">
         <pattern>
-          <option name="PATTERN" value="com.sf.proxy.cglib.*" />
+          <option name="PATTERN" value="com.sf.proxy.jdk.*" />
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
@@ -153,7 +144,7 @@
         <option name="Make" enabled="true" />
       </method>
     </configuration>
-    <configuration name="JdkDemo (1)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
+    <configuration name="JdkDemo (3)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
       <option name="MAIN_CLASS_NAME" value="com.sf.proxy.jdk.JdkDemo" />
       <module name="spring-demo" />
       <extension name="coverage">
@@ -166,7 +157,7 @@
         <option name="Make" enabled="true" />
       </method>
     </configuration>
-    <configuration name="JdkDemo (2)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
+    <configuration name="JdkDemo" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
       <option name="MAIN_CLASS_NAME" value="com.sf.proxy.jdk.JdkDemo" />
       <module name="spring-demo" />
       <extension name="coverage">
@@ -179,49 +170,63 @@
         <option name="Make" enabled="true" />
       </method>
     </configuration>
-    <configuration name="JdkDemo (3)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
-      <option name="MAIN_CLASS_NAME" value="com.sf.proxy.jdk.JdkDemo" />
+    <configuration name="TestAop.test" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
       <module name="spring-demo" />
       <extension name="coverage">
         <pattern>
-          <option name="PATTERN" value="com.sf.proxy.jdk.*" />
+          <option name="PATTERN" value="com.sf.*" />
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <option name="PACKAGE_NAME" value="com.sf" />
+      <option name="MAIN_CLASS_NAME" value="com.sf.TestAop" />
+      <option name="METHOD_NAME" value="test" />
+      <option name="TEST_OBJECT" value="method" />
       <method v="2">
         <option name="Make" enabled="true" />
       </method>
     </configuration>
-    <configuration name="JdkDemo" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
-      <option name="MAIN_CLASS_NAME" value="com.sf.proxy.jdk.JdkDemo" />
+    <configuration name="TestAop.testAdvisor" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
       <module name="spring-demo" />
       <extension name="coverage">
         <pattern>
-          <option name="PATTERN" value="com.sf.proxy.jdk.*" />
+          <option name="PATTERN" value="com.sf.*" />
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <option name="PACKAGE_NAME" value="com.sf" />
+      <option name="MAIN_CLASS_NAME" value="com.sf.TestAop" />
+      <option name="METHOD_NAME" value="testAdvisor" />
+      <option name="TEST_OBJECT" value="method" />
       <method v="2">
         <option name="Make" enabled="true" />
       </method>
     </configuration>
     <list>
-      <item itemvalue="Application.JdkDemo (1)" />
       <item itemvalue="Application.JdkDemo (2)" />
       <item itemvalue="Application.JdkDemo (3)" />
       <item itemvalue="Application.JdkDemo" />
-      <item itemvalue="Application.CglibClient" />
+      <item itemvalue="JUnit.TestAop.test" />
+      <item itemvalue="JUnit.TestAop.testAdvisor" />
     </list>
     <recent_temporary>
       <list>
-        <item itemvalue="Application.JdkDemo (1)" />
+        <item itemvalue="JUnit.TestAop.testAdvisor" />
+        <item itemvalue="JUnit.TestAop.test" />
+        <item itemvalue="Application.JdkDemo" />
         <item itemvalue="Application.JdkDemo (3)" />
         <item itemvalue="Application.JdkDemo (2)" />
-        <item itemvalue="Application.JdkDemo" />
-        <item itemvalue="Application.CglibClient" />
       </list>
     </recent_temporary>
   </component>
+  <component name="SharedIndexes">
+    <attachedChunks>
+      <set>
+        <option value="bundled-jdk-9f38398b9061-18abd8497189-intellij.indexing.shared.core-IU-241.14494.240" />
+        <option value="bundled-js-predefined-1d06a55b98c1-74d2a5396914-JavaScript-IU-241.14494.240" />
+      </set>
+    </attachedChunks>
+  </component>
   <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
   <component name="TaskManager">
     <task active="true" id="Default" summary="Default task">
@@ -237,7 +242,9 @@
       <workItem from="1713086100573" duration="122000" />
       <workItem from="1713332000735" duration="13027000" />
       <workItem from="1713574818502" duration="20981000" />
-      <workItem from="1713936457175" duration="10962000" />
+      <workItem from="1713936457175" duration="12171000" />
+      <workItem from="1714183148490" duration="130000" />
+      <workItem from="1714183284857" duration="7089000" />
     </task>
     <task id="LOCAL-00001" summary="0403 javaSE">
       <option name="closed" value="true" />
@@ -295,7 +302,15 @@
       <option name="project" value="LOCAL" />
       <updated>1713603930646</updated>
     </task>
-    <option name="localTasksCounter" value="8" />
+    <task id="LOCAL-00008" summary="0424 spring proxy">
+      <option name="closed" value="true" />
+      <created>1713949306918</created>
+      <option name="number" value="00008" />
+      <option name="presentableId" value="LOCAL-00008" />
+      <option name="project" value="LOCAL" />
+      <updated>1713949306918</updated>
+    </task>
+    <option name="localTasksCounter" value="9" />
     <servers />
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -427,7 +442,8 @@
     <MESSAGE value="0417 spring" />
     <MESSAGE value="0420 spring lifecycle" />
     <MESSAGE value="0420 spring ioc" />
-    <option name="LAST_COMMIT_MESSAGE" value="0420 spring ioc" />
+    <MESSAGE value="0424 spring proxy" />
+    <option name="LAST_COMMIT_MESSAGE" value="0424 spring proxy" />
   </component>
   <component name="XSLT-Support.FileAssociations.UIState">
     <expand />

+ 12 - 0
spring-demo/pom.xml

@@ -41,6 +41,18 @@
             <version>3.3.0</version>
         </dependency>
 
+        <!--aspectj支持-->
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjrt</artifactId>
+            <version>1.9.22</version>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <version>1.9.22</version>
+        </dependency>
+
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter</artifactId>

+ 11 - 0
spring-demo/src/main/java/com/sf/aop/BaseService.java

@@ -0,0 +1,11 @@
+package com.sf.aop;
+
+
+public interface BaseService {
+
+    // 吃饭
+    void eat(); // JoinCut 连接点
+
+    // 上厕所
+    void wc(); // JoinCut 连接点
+}

+ 14 - 0
spring-demo/src/main/java/com/sf/aop/MyAfterAdvice.java

@@ -0,0 +1,14 @@
+package com.sf.aop;
+
+import org.springframework.aop.AfterReturningAdvice;
+
+import java.lang.reflect.Method;
+
+// 后置通知
+public class MyAfterAdvice implements AfterReturningAdvice {
+
+    @Override
+    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
+        System.out.println("要洗手");
+    }
+}

+ 15 - 0
spring-demo/src/main/java/com/sf/aop/MyBeforeAdvice.java

@@ -0,0 +1,15 @@
+package com.sf.aop;
+
+import org.springframework.aop.MethodBeforeAdvice;
+
+import java.lang.reflect.Method;
+
+// 实现通知的接口 前置通知
+public class MyBeforeAdvice implements MethodBeforeAdvice {
+
+    // 切面,对应代理模式中的次要业务
+    @Override
+    public void before(Method method, Object[] objects, Object o) throws Throwable {
+        System.out.println("要洗手");
+    }
+}

+ 15 - 0
spring-demo/src/main/java/com/sf/aop/Person.java

@@ -0,0 +1,15 @@
+package com.sf.aop;
+
+// 实现类
+public class Person implements BaseService {
+
+    @Override
+    public void eat() { // 切入点PointCut,对应代理模式中的主要业务方法
+        System.out.println("吃饭");
+    }
+
+    @Override
+    public void wc() { // 切入点PointCut,对应代理模式中的主要业务方法
+        System.out.println("上厕所");
+    }
+}

+ 31 - 0
spring-demo/src/main/java/com/sf/aop/advisor/EatMethodMatcher.java

@@ -0,0 +1,31 @@
+package com.sf.aop.advisor;
+
+
+import org.springframework.aop.MethodMatcher;
+
+import java.lang.reflect.Method;
+
+// 类过滤之后 还要进行方法的匹配
+// aop的接口 MethodMatcher
+public class EatMethodMatcher implements MethodMatcher {
+
+    // 实现方法的匹配逻辑
+    @Override
+    public boolean matches(Method method, Class<?> targetClass) {
+        if(method.getName().equals("eat")){
+            // 对方法的匹配验证
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isRuntime() {
+        return false;
+    }
+
+    @Override
+    public boolean matches(Method method, Class<?> targetClass, Object... args) {
+        return false;
+    }
+}

+ 19 - 0
spring-demo/src/main/java/com/sf/aop/advisor/MyClassFilter.java

@@ -0,0 +1,19 @@
+package com.sf.aop.advisor;
+
+import com.sf.aop.Person;
+import org.springframework.aop.ClassFilter;
+
+
+// 顾问的使用方式
+// ClassFilter是aop提供的类过滤器
+public class MyClassFilter implements ClassFilter {
+
+    @Override
+    public boolean matches(Class<?> clazz) {
+        if(clazz == Person.class){
+            // 要代理的是Person类
+            return true;
+        }
+        return false;
+    }
+}

+ 32 - 0
spring-demo/src/main/java/com/sf/aop/advisor/MyPointCut.java

@@ -0,0 +1,32 @@
+package com.sf.aop.advisor;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+
+// 连接点
+// 解决要代理哪个类的哪个方法
+public class MyPointCut implements Pointcut {
+
+    private ClassFilter classFilter;
+
+    private MethodMatcher methodMatcher;
+
+    @Override
+    public ClassFilter getClassFilter() {
+        return classFilter;
+    }
+
+    @Override
+    public MethodMatcher getMethodMatcher() {
+        return methodMatcher;
+    }
+
+    public void setClassFilter(ClassFilter classFilter) {
+        this.classFilter = classFilter;
+    }
+
+    public void setMethodMatcher(MethodMatcher methodMatcher) {
+        this.methodMatcher = methodMatcher;
+    }
+}

+ 32 - 0
spring-demo/src/main/java/com/sf/aop/advisor/MyPointCutAdvisor.java

@@ -0,0 +1,32 @@
+package com.sf.aop.advisor;
+
+import org.aopalliance.aop.Advice;
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.PointcutAdvisor;
+
+// 顾问类
+public class MyPointCutAdvisor implements PointcutAdvisor {
+
+    // 在方法的执行之前或者之后  要确定通知的类型
+    private Advice advice;
+    // 匹配到的类和方法  要代理的具体方法
+    private Pointcut pointcut;
+
+    @Override
+    public Pointcut getPointcut() {
+        return pointcut;
+    }
+
+    @Override
+    public Advice getAdvice() {
+        return advice;
+    }
+
+    public void setAdvice(Advice advice) {
+        this.advice = advice;
+    }
+
+    public void setPointcut(Pointcut pointcut) {
+        this.pointcut = pointcut;
+    }
+}

+ 26 - 0
spring-demo/src/main/java/com/sf/aop/advisor/WcMethodMatcher.java

@@ -0,0 +1,26 @@
+package com.sf.aop.advisor;
+
+import org.springframework.aop.MethodMatcher;
+
+import java.lang.reflect.Method;
+
+public class WcMethodMatcher implements MethodMatcher {
+
+    @Override
+    public boolean matches(Method method, Class<?> targetClass) {
+        if (method.getName().equals("wc")) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isRuntime() {
+        return false;
+    }
+
+    @Override
+    public boolean matches(Method method, Class<?> targetClass, Object... args) {
+        return false;
+    }
+}

+ 14 - 0
spring-demo/src/main/java/com/sf/aspect/Audience.java

@@ -0,0 +1,14 @@
+package com.sf.aspect;
+
+public class Audience {
+
+    // 表演之前 入场
+    public void takeSeats() {
+        System.out.println("入场,坐到位置上");
+    }
+
+    // 表演之后 鼓掌
+    public void applause() {
+        System.out.println("呱唧呱唧");
+    }
+}

+ 10 - 0
spring-demo/src/main/java/com/sf/aspect/CrossTalk.java

@@ -0,0 +1,10 @@
+package com.sf.aspect;
+
+
+public class CrossTalk implements Performance{
+
+    @Override
+    public void perform() {
+        System.out.println("表演一段相声");
+    }
+}

+ 7 - 0
spring-demo/src/main/java/com/sf/aspect/Performance.java

@@ -0,0 +1,7 @@
+package com.sf.aspect;
+
+// 构建一个表演的场景
+public interface Performance {
+
+    void perform();
+}

+ 55 - 0
spring-demo/src/main/resources/spring-advisor.xml

@@ -0,0 +1,55 @@
+<?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
+        https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+    <!-- 注册被监控的实现类 -->
+    <bean id="person" class="com.sf.aop.Person"></bean>
+
+    <!-- 注册通知实现类 -->
+    <bean id="beforeAdvice" class="com.sf.aop.MyBeforeAdvice"></bean>
+    <bean id="afterAdvice" class="com.sf.aop.MyAfterAdvice"></bean>
+
+    <!-- 声明类和方法的匹配 -->
+    <bean id="classFilter" class="com.sf.aop.advisor.MyClassFilter"/>
+    <bean id="eatMethodMatcher" class="com.sf.aop.advisor.EatMethodMatcher"/>
+    <bean id="wcMethodMatcher" class="com.sf.aop.advisor.WcMethodMatcher"/>
+
+    <!-- 此时关注的是 Person类的eat方法 -->
+    <bean id="eatPointCut" class="com.sf.aop.advisor.MyPointCut">
+        <property name="classFilter" ref="classFilter"></property>
+        <property name="methodMatcher" ref="eatMethodMatcher"></property>
+    </bean>
+
+    <!-- 此时关注的是 Person类的wc方法 -->
+    <bean id="wcPointCut" class="com.sf.aop.advisor.MyPointCut">
+        <property name="classFilter" ref="classFilter"></property>
+        <property name="methodMatcher" ref="wcMethodMatcher"></property>
+    </bean>
+
+    <bean id="eatAdvisor" class="com.sf.aop.advisor.MyPointCutAdvisor">
+        <property name="advice" ref="beforeAdvice"></property>
+        <property name="pointcut" ref="eatPointCut"></property>
+    </bean>
+
+    <bean id="wcAdvisor" class="com.sf.aop.advisor.MyPointCutAdvisor">
+        <property name="advice" ref="afterAdvice"></property>
+        <property name="pointcut" ref="wcPointCut"></property>
+    </bean>
+
+    <!-- 注册代理监控对象生产工厂 -->
+    <bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
+        <!-- 目标对象,为 person 创建一个代理对象 -->
+        <property name="target" ref="person"/>
+<!--        <property name="interceptorNames" value="eatAdvisor,wcAdvisor"/>-->
+        <!-- 拦截的名字 -->
+        <property name="interceptorNames">
+            <array>
+                <value>eatAdvisor</value>
+                <value>wcAdvisor</value>
+            </array>
+        </property>
+    </bean>
+
+</beans>

+ 23 - 0
spring-demo/src/main/resources/spring-aop.xml

@@ -0,0 +1,23 @@
+<?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
+        https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+    <!-- 注册被监控的实现类 -->
+    <bean id="person" class="com.sf.aop.Person"></bean>
+
+    <!-- 注册通知实现类 -->
+    <bean id="before" class="com.sf.aop.MyBeforeAdvice"></bean>
+
+    <!-- 注册代理监控对象生产工厂 -->
+    <bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
+        <!-- 目标对象,为 person 创建一个代理对象 -->
+        <property name="target" ref="person"/>
+        <property name="interceptorNames">
+            <array>
+                <value>before</value>
+            </array>
+        </property>
+    </bean>
+</beans>

+ 21 - 0
spring-demo/src/main/resources/spring-aspect.xml

@@ -0,0 +1,21 @@
+<?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
+        https://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/aop
+        https://www.springframework.org/schema/aop/spring-aop.xsd">
+
+    <!-- 核心逻辑  被代理的对象 -->
+    <bean id="crossTalk" class="com.sf.aspect.CrossTalk"></bean>
+    <!-- 非核心逻辑  核心逻辑前后要做的事儿 -->
+    <bean id="audience" class="com.sf.aspect.Audience"></bean>
+
+
+    <aop:config>
+        <aop:aspect ref="audience">
+            <aop:pointcut id="pointcut" expression="execution(* com.sf.aspect.Performance.perform())"/>
+        </aop:aspect>
+    </aop:config>
+</beans>

+ 26 - 0
spring-demo/src/test/java/com/sf/TestAop.java

@@ -0,0 +1,26 @@
+package com.sf;
+
+import com.sf.aop.BaseService;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class TestAop {
+
+    @Test
+    public void test() {
+        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
+        BaseService personProxy = (BaseService) context.getBean("personProxy");
+        personProxy.eat();
+        personProxy.wc();
+    }
+
+
+    @Test
+    public void testAdvisor() {
+        ApplicationContext context = new ClassPathXmlApplicationContext("spring-advisor.xml");
+        BaseService personProxy = (BaseService) context.getBean("personProxy");
+        personProxy.eat();
+        personProxy.wc();
+    }
+}