소스 검색

0112 spring aop

Qing 1 년 전
부모
커밋
6feeb474de
36개의 변경된 파일783개의 추가작업 그리고 2개의 파일을 삭제
  1. 1 1
      spring-demo/.idea/encodings.xml
  2. 10 0
      spring-demo/src/main/java/com/sf/annotation/House.java
  3. 8 0
      spring-demo/src/main/java/com/sf/aop/BaseService.java
  4. 13 0
      spring-demo/src/main/java/com/sf/aop/MyAfterAdvice.java
  5. 18 0
      spring-demo/src/main/java/com/sf/aop/MyBeforeAdvice.java
  6. 14 0
      spring-demo/src/main/java/com/sf/aop/Person.java
  7. 38 0
      spring-demo/src/main/java/com/sf/aop/advisor/EatMethodMatcher.java
  8. 26 0
      spring-demo/src/main/java/com/sf/aop/advisor/MyClassFilter.java
  9. 33 0
      spring-demo/src/main/java/com/sf/aop/advisor/MyPointCut.java
  10. 48 0
      spring-demo/src/main/java/com/sf/aop/advisor/MyPointCutAdvisor.java
  11. 36 0
      spring-demo/src/main/java/com/sf/aop/advisor/WcMethodMatcher.java
  12. 28 0
      spring-demo/src/main/java/com/sf/config/MyBean.java
  13. 49 0
      spring-demo/src/main/java/com/sf/config/PropertiesConfig.java
  14. 11 0
      spring-demo/src/main/java/com/sf/config/SpringConfig.java
  15. 23 0
      spring-demo/src/main/java/com/sf/config/condition/MacCondition.java
  16. 36 0
      spring-demo/src/main/java/com/sf/config/condition/Person.java
  17. 21 0
      spring-demo/src/main/java/com/sf/config/condition/PersonConfig.java
  18. 30 0
      spring-demo/src/main/java/com/sf/config/condition/WindowsCondition.java
  19. 15 0
      spring-demo/src/main/java/com/sf/proxy/GamePlayer.java
  20. 19 0
      spring-demo/src/main/java/com/sf/proxy/GamePlayerProxy.java
  21. 9 0
      spring-demo/src/main/java/com/sf/proxy/IGamePlayer.java
  22. 11 0
      spring-demo/src/main/java/com/sf/proxy/Test.java
  23. 29 0
      spring-demo/src/main/java/com/sf/proxy/dynamic/MyInvocationHandler.java
  24. 24 0
      spring-demo/src/main/java/com/sf/proxy/dynamic/Test.java
  25. 50 0
      spring-demo/src/main/resources/bean-advisor.xml
  26. 27 0
      spring-demo/src/main/resources/bean-aop.xml
  27. 3 0
      spring-demo/src/main/resources/book.properties
  28. 3 0
      spring-demo/src/main/resources/test.properties
  29. 2 1
      spring-demo/src/test/java/com/sf/HelloJuint.java
  30. 11 0
      spring-demo/src/test/java/com/sf/Test.java
  31. 17 0
      spring-demo/src/test/java/com/sf/TestAdvisor.java
  32. 17 0
      spring-demo/src/test/java/com/sf/TestAop.java
  33. 19 0
      spring-demo/src/test/java/com/sf/TestConfig.java
  34. 37 0
      spring-demo/src/test/java/com/sf/TestPerson.java
  35. 37 0
      spring-demo/src/test/java/com/sf/TestProperties.java
  36. 10 0
      spring-demo/src/test/java/com/sf/TestPrototype.java

+ 1 - 1
spring-demo/.idea/encodings.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="Encoding">
+  <component name="Encoding" native2AsciiForPropertiesFiles="true" defaultCharsetForPropertiesFiles="GB18030">
     <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
   </component>

+ 10 - 0
spring-demo/src/main/java/com/sf/annotation/House.java

@@ -6,6 +6,16 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
+/**
+ * 当使用@Component 声明House是一个bean的时候
+ * 默认是单例的  同时 会将House小写 使用“house”作为beanId
+ * house = new House();  // 通过反射创建的对象
+ * Map <"house",house>
+ *     <"chair",chair>
+ *     <"teacher",teacher>
+ *          chair.setTeacher(teacher)
+ *          house.setChair(chair)
+ */
 @Component
 public class House {
 

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

@@ -0,0 +1,8 @@
+package com.sf.aop;
+
+public interface BaseService {
+
+    void eat(); // JoinCut 连接点
+
+    void wc(); // JoinCut 连接点
+}

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

@@ -0,0 +1,13 @@
+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("···洗手···");
+    }
+}

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

@@ -0,0 +1,18 @@
+package com.sf.aop;
+
+import org.springframework.aop.MethodBeforeAdvice;
+
+import java.lang.reflect.Method;
+
+// 动态代理 是需要实现接口的
+//   动态代理不会自己去创建代理类  但需要通过接口  把代理要做的逻辑传进去
+//   MethodBeforeAdvice 方法前置通知  在调用方法之前 要做什么
+public class MyBeforeAdvice implements MethodBeforeAdvice {
+    // 前置处理的 通知
+
+    // 切面,对应代理模式中的次要业务
+    @Override
+    public void before(Method method, Object[] objects, Object o) throws Throwable {
+        System.out.println("···洗手···");
+    }
+}

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

@@ -0,0 +1,14 @@
+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("上厕所");
+    }
+}

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

@@ -0,0 +1,38 @@
+package com.sf.aop.advisor;
+
+import org.springframework.aop.MethodMatcher;
+import java.lang.reflect.Method;
+
+// 在方法级别的拦截
+// 使用接口 MethodMatcher
+//  在实现方法中 判断是否要拦截
+public class EatMethodMatcher implements MethodMatcher {
+    /**
+     * 监控接口比如BaseService,没有重载方法,每一个方法名称都是唯一的,
+     * 此时采用 static 检测方式,只根据方法名称来进行判断,如果有重载方法,
+     * 可以使用下方的 matches() 方法
+     * 业务:只想对 Person 类中的 eat() 方法提供织入
+     *
+     * @param method      接口中的某一个方法
+     * @param targetClass 接口中的实现类
+     * @return
+     */
+    @Override
+    public boolean matches(Method method, Class<?> targetClass) {
+        String methodName = method.getName();
+        if ("eat".equals(methodName)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isRuntime() {
+        return false;
+    }
+
+    @Override
+    public boolean matches(Method method, Class<?> targetClass, Object... args) {
+        return false;
+    }
+}

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

@@ -0,0 +1,26 @@
+package com.sf.aop.advisor;
+
+import com.sf.aop.Person;
+import org.springframework.aop.ClassFilter;
+
+// 在类的级别上进行过滤和拦截
+// 使用接口 ClassFilter
+public class MyClassFilter implements ClassFilter {
+
+    /**
+     * 1、一个接口下有多个实现类
+     * 2、判断当前实现类是不是我们织入方式的目标类
+     * 3、BaseService 接口我们只想管理 Person,而不管理 Dog
+     *
+     * @param clazz 当前被拦截的类,可能是 Person,也可能是 Dog
+     * @return
+     */
+    @Override
+    public boolean matches(Class<?> clazz) {
+        // 比较当前处理的类 和 要拦截的类 是否匹配
+        if (clazz == Person.class) {
+            return true; // 告诉顾问,当前类是需要我们提供织入服务的
+        }
+        return false;
+    }
+}

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

@@ -0,0 +1,33 @@
+package com.sf.aop.advisor;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+
+// 切点 Pointcut
+// 是将类的过滤器和方法的拦截器  关联起来  通过先拦截类再拦截方法  进一步确定 要代理的逻辑
+public class MyPointCut implements Pointcut {
+
+    // 使用依赖注入,需要提供 setter() 方法
+    private ClassFilter classFilter;
+
+    private MethodMatcher methodMatcher;
+
+    @Override
+    public ClassFilter getClassFilter() {
+        return this.classFilter;
+    }
+
+    @Override
+    public MethodMatcher getMethodMatcher() {
+        return this.methodMatcher;
+    }
+
+    public void setClassFilter(ClassFilter classFilter) {
+        this.classFilter = classFilter;
+    }
+
+    public void setMethodMatcher(MethodMatcher methodMatcher) {
+        this.methodMatcher = methodMatcher;
+    }
+}

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

@@ -0,0 +1,48 @@
+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 {
+
+    //  advice  ->  eat()  wc() ->  advice
+
+    //  [ advice通知  ->   pointCut切点 「 eat()连接点 」]  advisor顾问
+    //  [ pointCut 「 wc() 」 ->  advice]   advisor顾问
+
+    //  EatAvisor顾问 { advice通知 , pointcut切点{classFilter methodMatcher} }
+    //  WCAvisor顾问 { advice通知 , pointcut切点{classFilter methodMatcher} }
+
+    //  最后通过代理工厂ProxyFactoryBean  把前面配置的拦截住
+
+    // 使用依赖注入,需要提供 setter() 方法
+    private Advice advice; // 次要业务以及次要业务与主要业务执行顺序
+
+    private Pointcut pointcut;// 当前拦截对象和对象调用主要业务方法 Person 和 .eat() 方法
+
+    @Override
+    public Pointcut getPointcut() {
+        return this.pointcut;
+    }
+
+    @Override
+    public Advice getAdvice() {
+        return this.advice;
+    }
+
+    @Override
+    public boolean isPerInstance() {
+        return false;
+    }
+
+    public void setAdvice(Advice advice) {
+        this.advice = advice;
+    }
+
+    public void setPointcut(Pointcut pointcut) {
+        this.pointcut = pointcut;
+    }
+}

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

@@ -0,0 +1,36 @@
+package com.sf.aop.advisor;
+
+import org.springframework.aop.MethodMatcher;
+import java.lang.reflect.Method;
+
+public class WcMethodMatcher implements MethodMatcher {
+
+    /**
+     * 监控接口比如BaseService,没有重载方法,每一个方法名称都是唯一的,
+     * 此时采用 static 检测方式,只根据方法名称来进行判断,如果有重载方法,
+     * 可以使用下方的 matches() 方法
+     * 业务:只想对 Person 类中的 wc() 方法提供织入
+     *
+     * @param method      接口中的某一个方法
+     * @param targetClass 接口中的实现类
+     * @return
+     */
+    @Override
+    public boolean matches(Method method, Class<?> targetClass) {
+        String methodName = method.getName();
+        if ("wc".equals(methodName)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isRuntime() {
+        return false;
+    }
+
+    @Override
+    public boolean matches(Method method, Class<?> targetClass, Object... args) {
+        return false;
+    }
+}

+ 28 - 0
spring-demo/src/main/java/com/sf/config/MyBean.java

@@ -0,0 +1,28 @@
+package com.sf.config;
+
+public class MyBean {
+
+    private String value;
+
+    public MyBean() {
+    }
+
+    public MyBean(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return "MyBean{" +
+                "value='" + value + '\'' +
+                '}';
+    }
+}

+ 49 - 0
spring-demo/src/main/java/com/sf/config/PropertiesConfig.java

@@ -0,0 +1,49 @@
+package com.sf.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.context.annotation.PropertySource;
+
+// 如果想通过配置文件 找到并解析properties 需要使用一个注解
+@Configuration
+@PropertySource("test.properties")
+public class PropertiesConfig {
+    // Map  <k1,v1> <k2,v2>
+
+    // 当加载好配置文件后 properties就是一个map
+    // 可以通过key 找到value
+    // 使用@Value注解  放在一个属性上
+    // 代表可以通过某个key找到value 并且注入到当前的属性上
+//    @Value("${k1}")
+//    @Value("k1")   //如果不使用表达式 赋值的是“值”本身
+//    @Value("${k3}")  // 如果表达式的key没有找到 赋值的是“表达式”本身
+    @Value("${k3:v3}")  // 如果表达式的key可能找不到  可以使用一个默认值 但如果能找到  默认值会被覆盖
+    private String myValue1;
+
+    @Value("${k2}")
+    private String myValue2;
+
+    // 由此 我们可以创建MyBean了  并且想要放入到容器中
+    // @Bean注解 是可以放在方法上的 方法的返回类型以及返回结果
+    // 就可以作为一个bean放入到spring的容器中  MyBean -> new MyBean("v1")
+    //   方法的名字是beanID   <"mybean1",new MyBean("v1")> <"mybean2",new MyBean("v2")>
+    @Profile("test")  // 在实际开发过程中  很有多环境 如果希望测试环境能够使用这个bean 可以这样配置
+    @Bean
+    public MyBean mybean1() {
+        return new MyBean(myValue1);
+    }
+
+    @Profile("prod")  // !test 代表的 不是test环境的其他环境
+    @Bean
+    public MyBean mybean2() {
+        return new MyBean(myValue2);
+    }
+
+    @Profile("dev")  // !test 代表的 不是test环境的其他环境
+    @Bean
+    public MyBean mybean3() {
+        return new MyBean(myValue1 + myValue2);
+    }
+}

+ 11 - 0
spring-demo/src/main/java/com/sf/config/SpringConfig.java

@@ -0,0 +1,11 @@
+package com.sf.config;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+// 声明这是一个spring的配置类  相当于是以前的xml文件
+// 全注解开发的方式  将xml的使用方式 简化为注解
+@Configuration
+@ComponentScan("com.sf.annotation")
+public class SpringConfig {
+}

+ 23 - 0
spring-demo/src/main/java/com/sf/config/condition/MacCondition.java

@@ -0,0 +1,23 @@
+package com.sf.config.condition;
+
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.env.Environment;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+public class MacCondition implements Condition {
+
+    @Override
+    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+        // 通过方法的形参 context 可以获取ioc的容器
+//        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
+        // 还可以通过context这个容器获取系统环境
+        Environment environment = context.getEnvironment();
+        // 可以由此获取操作系统的名字
+        String property = environment.getProperty("os.name");
+        if(property.contains("Mac")){
+            return true;
+        }
+        return false;
+    }
+}

+ 36 - 0
spring-demo/src/main/java/com/sf/config/condition/Person.java

@@ -0,0 +1,36 @@
+package com.sf.config.condition;
+
+public class Person {
+
+    private String name;
+    private Integer age;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public Person() {
+    }
+
+    public Person(String name, Integer age) {
+        this.name = name;
+        this.age = age;
+    }
+
+    @Override
+    public String toString() {
+        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
+    }
+}

+ 21 - 0
spring-demo/src/main/java/com/sf/config/condition/PersonConfig.java

@@ -0,0 +1,21 @@
+package com.sf.config.condition;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class PersonConfig {
+
+    @Conditional(WindowsCondition.class)
+    @Bean
+    public Person person1(){
+        return new Person("Bill Gates",60);
+    }
+
+    @Conditional(MacCondition.class)
+    @Bean
+    public Person person2(){
+        return new Person("Steve Jobs",45);
+    }
+}

+ 30 - 0
spring-demo/src/main/java/com/sf/config/condition/WindowsCondition.java

@@ -0,0 +1,30 @@
+package com.sf.config.condition;
+
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.env.Environment;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+/**
+ * 要自己实现条件装配的功能
+ * 需要实现spring提供的Condition接口
+ * 这个接口的方法 叫做matches 要给定符合条件的逻辑
+ *   也就是说  在这个方法中 编写你要满足的条件  满足了条件返回true 不满足返回false
+ */
+public class WindowsCondition implements Condition {
+
+    @Override
+    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+        // 通过方法的形参 context 可以获取ioc的容器
+//        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
+        // 还可以通过context这个容器获取系统环境
+        Environment environment = context.getEnvironment();
+        // 可以由此获取操作系统的名字
+        String property = environment.getProperty("os.name");
+        if(property.contains("Windows")){
+            return true;
+        }
+        return false;
+    }
+}

+ 15 - 0
spring-demo/src/main/java/com/sf/proxy/GamePlayer.java

@@ -0,0 +1,15 @@
+package com.sf.proxy;
+
+public class GamePlayer implements IGamePlayer {
+
+    private String name;
+
+    public GamePlayer(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public void playGame() {
+        System.out.println("代练" + name + "接手游戏");
+    }
+}

+ 19 - 0
spring-demo/src/main/java/com/sf/proxy/GamePlayerProxy.java

@@ -0,0 +1,19 @@
+package com.sf.proxy;
+
+/**
+ * 接受代理需求的店铺
+ */
+public class GamePlayerProxy implements IGamePlayer{
+    // 店铺合作的小代
+    private IGamePlayer player;
+
+    public GamePlayerProxy(IGamePlayer player) {
+        this.player = player;
+    }
+
+    @Override
+    public void playGame() {
+        // 指派小代去玩儿游戏
+        this.player.playGame();
+    }
+}

+ 9 - 0
spring-demo/src/main/java/com/sf/proxy/IGamePlayer.java

@@ -0,0 +1,9 @@
+package com.sf.proxy;
+
+/**
+ * 玩游戏的需求
+ */
+public interface IGamePlayer {
+
+    void playGame();
+}

+ 11 - 0
spring-demo/src/main/java/com/sf/proxy/Test.java

@@ -0,0 +1,11 @@
+package com.sf.proxy;
+
+public class Test {
+
+    // 一种游戏代练的场景
+    public static void main(String[] args) {
+        IGamePlayer player = new GamePlayer("zhangsan");
+        IGamePlayer proxy = new GamePlayerProxy(player);
+        proxy.playGame();
+    }
+}

+ 29 - 0
spring-demo/src/main/java/com/sf/proxy/dynamic/MyInvocationHandler.java

@@ -0,0 +1,29 @@
+package com.sf.proxy.dynamic;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class MyInvocationHandler<T> implements InvocationHandler {
+    private T target;
+
+    public MyInvocationHandler(T target) {
+        this.target = target;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        this.doBefore();
+        Object result = method.invoke(target, args);
+        this.doAfter();
+        return result;
+    }
+
+    private void doBefore() {
+        System.out.println("前置处理");
+    }
+
+    private void doAfter() {
+        System.out.println("后置处理");
+    }
+}
+

+ 24 - 0
spring-demo/src/main/java/com/sf/proxy/dynamic/Test.java

@@ -0,0 +1,24 @@
+package com.sf.proxy.dynamic;
+
+import com.sf.proxy.GamePlayer;
+import com.sf.proxy.IGamePlayer;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
+public class Test {
+
+    public static void main(String[] args) {
+        IGamePlayer player = new GamePlayer("张三");
+        InvocationHandler handler = new MyInvocationHandler<>(player);
+        // 创建代理对象 代理对象执行每个方法都会替换成执行InvocationHandler中的invoke方法
+        // 通过Proxy创建代理对象  传入小代的类加载器 传入代练需求 传入处理方式
+        IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(
+                player.getClass().getClassLoader(), new Class[]{IGamePlayer.class}, handler);
+        proxy.playGame();
+
+//        IGamePlayer player = new GamePlayer("zhangsan");
+//        IGamePlayer proxy = new GamePlayerProxy(player);
+//        proxy.playGame();
+    }
+}

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

@@ -0,0 +1,50 @@
+<?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="after" class="com.sf.aop.MyAfterAdvice"></bean>
+
+    <!-- 注册类型过滤器 -->
+    <bean id="classFilter" class="com.sf.aop.advisor.MyClassFilter"></bean>
+    <!-- 注册方法匹配器 -->
+    <bean id="eatMethodMatcher" class="com.sf.aop.advisor.EatMethodMatcher"></bean>
+    <bean id="wcMethodMatcher" class="com.sf.aop.advisor.WcMethodMatcher"></bean>
+
+    <!-- 注册切入点 -->
+    <bean id="eatPointcut" class="com.sf.aop.advisor.MyPointCut">
+        <property name="classFilter" ref="classFilter"></property>
+        <property name="methodMatcher" ref="eatMethodMatcher"></property>
+    </bean>
+    <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="before"></property>
+        <property name="pointcut" ref="eatPointcut"></property>
+    </bean>
+    <bean id="wcAdvisor" class="com.sf.aop.advisor.MyPointCutAdvisor">
+        <property name="advice" ref="after"></property>
+        <property name="pointcut" ref="wcPointcut"></property>
+    </bean>
+
+
+    <!-- 注册代理对象工厂 -->
+    <!--
+        此时生成的代理对象,只会负责 Person.eat() 方法进行监控,
+        与 Advice 不同,不会对 BaseService 所有的方法进行监控
+     -->
+    <bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
+        <property name="target" ref="person"></property>
+        <property name="interceptorNames" value="eatAdvisor,wcAdvisor"></property>
+    </bean>
+</beans>

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

@@ -0,0 +1,27 @@
+<?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>
+
+    <!-- 注册代理监控对象生产工厂 ProxyFactoryBean -->
+    <bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
+        <!-- 目标对象,为 person 创建一个代理对象
+          次要的业务逻辑 包裹主要的业务逻辑  目标(要包裹谁/要代理谁) -->
+        <property name="target" ref="person"/>
+        <!-- 拦截器的名字 interceptorNames  可以为多个  次要逻辑可以有多个 -->
+        <!--   所以数据的结构是数组  数组的使用方式是 标签array -->
+        <!--   数组中的值 是beanId 实现了通知接口的类的对象-->
+        <property name="interceptorNames">
+            <array>
+                <value>before</value>
+            </array>
+        </property>
+    </bean>
+</beans>

+ 3 - 0
spring-demo/src/main/resources/book.properties

@@ -0,0 +1,3 @@
+javaSE=\u75AF\u72C2java\u8BB2\u4E49
+  mysql=mysql\u5FC5\u77E5\u5FC5\u4F1A
+  JavaEE=\u6DF1\u5165\u5206\u6790JavaWeb\u6280\u672F\u5185\u5E55

+ 3 - 0
spring-demo/src/main/resources/test.properties

@@ -0,0 +1,3 @@
+k1=\u6D4B\u8BD5
+k2=v2
+k3=v333

+ 2 - 1
spring-demo/src/test/java/com/sf/HelloJuint.java

@@ -17,7 +17,8 @@ public class HelloJuint {
 
     @BeforeEach
     public void setUp() {
-        context = new ClassPathXmlApplicationContext("bean.xml");
+        System.out.println("@BeforeEach,测试开始");
+//        context = new ClassPathXmlApplicationContext("bean.xml");
     }
 
     @AfterEach

+ 11 - 0
spring-demo/src/test/java/com/sf/Test.java

@@ -0,0 +1,11 @@
+package com.sf;
+
+//import org.junit.jupiter.api.Test;
+
+public class Test {
+
+    @org.junit.jupiter.api.Test
+    public void test(){
+        System.out.println("hello");
+    }
+}

+ 17 - 0
spring-demo/src/test/java/com/sf/TestAdvisor.java

@@ -0,0 +1,17 @@
+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 TestAdvisor {
+
+    @Test
+    public void test() {
+        ApplicationContext factory = new ClassPathXmlApplicationContext("bean-advisor.xml");
+        BaseService personProxy = (BaseService) factory.getBean("personProxy");
+        personProxy.eat();
+        personProxy.wc();
+    }
+}

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

@@ -0,0 +1,17 @@
+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("bean-aop.xml");
+        BaseService personProxy = (BaseService) context.getBean("personProxy");
+        personProxy.eat();
+        personProxy.wc();
+    }
+}

+ 19 - 0
spring-demo/src/test/java/com/sf/TestConfig.java

@@ -0,0 +1,19 @@
+package com.sf;
+
+import com.sf.annotation.House;
+import com.sf.config.SpringConfig;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+@SpringJUnitConfig(SpringConfig.class)
+public class TestConfig {
+
+    @Autowired
+    private House house;
+
+    @Test
+    public void test(){
+        System.out.println(house);
+    }
+}

+ 37 - 0
spring-demo/src/test/java/com/sf/TestPerson.java

@@ -0,0 +1,37 @@
+package com.sf;
+
+import com.sf.config.condition.Person;
+import com.sf.config.condition.PersonConfig;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+import java.util.Map;
+
+@SpringJUnitConfig(PersonConfig.class)
+public class TestPerson {
+
+    @Autowired
+    private ApplicationContext context;
+
+    @Test
+    public void test(){
+        Person person1 = context.getBean("person1", Person.class);
+        Person person2 = context.getBean("person2", Person.class);
+        System.out.println(person1);
+        System.out.println(person2);
+
+        Map<String, Person> map = context.getBeansOfType(Person.class);
+        System.out.println(map);
+    }
+
+    @Test
+    public void test1(){
+        String property = context.getEnvironment().getProperty("os.name");
+        System.out.println(property);
+
+        Map<String, Person> map = context.getBeansOfType(Person.class);
+        System.out.println(map);
+    }
+}

+ 37 - 0
spring-demo/src/test/java/com/sf/TestProperties.java

@@ -0,0 +1,37 @@
+package com.sf;
+
+import com.sf.config.MyBean;
+import com.sf.config.PropertiesConfig;
+import jakarta.annotation.Resource;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Profile;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+// 激活某一个环境  dev test prod sit
+@ActiveProfiles("dev")
+@SpringJUnitConfig(PropertiesConfig.class)
+public class TestProperties {
+
+    @Autowired
+//    @Qualifier("mybean1")
+    private MyBean mybean1;
+
+    // 先通过名字去找 MyBean  mybean2没有  再根据类型去找 MyBean 找到mybean1
+    @Resource
+    private MyBean mybean2;
+
+//    @Resource
+//    private MyBean mybean3;
+
+    @Test
+    public void test() {
+        System.out.println(mybean1);
+        System.out.println(mybean2);
+
+        System.out.println(mybean1 == mybean2);
+//        System.out.println(mybean3);
+    }
+}

+ 10 - 0
spring-demo/src/test/java/com/sf/TestPrototype.java

@@ -3,6 +3,7 @@ package com.sf;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
 
 public class TestPrototype {
 
@@ -26,4 +27,13 @@ public class TestPrototype {
         ((ClassPathXmlApplicationContext) context).close();
 
     }
+
+    @Test
+    public void testFile(){
+        ApplicationContext context =
+                new FileSystemXmlApplicationContext("src/main/resources/bean.xml");
+        User user = context.getBean("user", User.class);
+        System.out.println(user);
+
+    }
 }