第一章:环境搭建

  • IDEA 2021+。
  • JDK 11+。
  • Maven 3.8。

  • pom.xml

  1. <!-- Spring -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-context</artifactId>
  5. <version>5.3.12</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework</groupId>
  9. <artifactId>spring-aspects</artifactId>
  10. <version>5.3.12</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework</groupId>
  14. <artifactId>spring-test</artifactId>
  15. <version>5.3.12</version>
  16. </dependency>
  17. <!-- junit单元测试 -->
  18. <dependency>
  19. <groupId>junit</groupId>
  20. <artifactId>junit</artifactId>
  21. <version>4.13.2</version>
  22. <scope>test</scope>
  23. </dependency>

第二章:根据类型获取 bean

2.1 情景一

  • bean 对应的类没有实现任何接口,根据 bean 本身的类型获取 bean。
  • ① 如果 IOC 容器中同类型的 bean 只有一个,那么可以根据 bean 本身的类型可以获取 bean 。
  • ② 如果 IOC 容器中同类型的 bean 不止一个,那么根据 bean 本身的类型获取 bean ,会抛出 NoUniqueBeanDefinitionException 异常。

  • 示例:

  • Hello.java
  1. package com.github.fairy.era.bean;
  2. /**
  3. * @author 许大仙
  4. * @version 1.0
  5. * @since 2021-11-09 07:56
  6. */
  7. public class Hello {
  8. }
  • applicationContext.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="hello" class="com.github.fairy.era.bean.Hello"></bean>
  6. </beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Hello hello = context.getBean(Hello.class);
        System.out.println("hello = " + hello);
    }
}
  • 结果:
hello = com.github.fairy.era.bean.Hello@1c7696c6
  • 示例:
  • Hello.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 07:56
 */
public class Hello {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="com.github.fairy.era.bean.Hello"></bean>

    <bean id="hello2" class="com.github.fairy.era.bean.Hello"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Hello hello = context.getBean(Hello.class);
        System.out.println("hello = " + hello);
    }
}
  • 结果:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.github.fairy.era.bean.Hello' available: expected single matching bean but found 2: hello,hello2

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1262)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
    at com.github.fairy.era.bean.SpringTest.test(SpringTest.java:19)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

2.2 情景二

  • bean 对应的类实现了接口,这个接口也只有一个实现类。
  • ① 根据接口类型可以获取到 bean 。
  • ② 根据实现类的类型可以获取到 bean 。
  • ③ 上面两种情况下,获取的 bean 是同一个对象。

  • 示例:

  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public interface Happy {

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public class HappyImpl implements Happy {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="happy" class="com.github.fairy.era.bean.impl.HappyImpl"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import com.github.fairy.era.bean.impl.HappyImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Happy happyImpl = context.getBean(HappyImpl.class);
        System.out.println("happyImpl = " + happyImpl);

        Happy happy = context.getBean(Happy.class);
        System.out.println("happy = " + happy);

        System.out.println(happy == happyImpl);
    }
}
  • 结果:
happyImpl = com.github.fairy.era.bean.impl.HappyImpl@6574a52c
happy = com.github.fairy.era.bean.impl.HappyImpl@6574a52c
true

2.3 情景三

  • 声明一个接口,接口有多个实现类,并且这多个实现类都放入到了 IOC 容器中。
  • ① 根据接口类型获取 bean ,会抛出 NoUniqueBeanDefinitionException 异常。
  • ② 根据实现类的类型可以正常获取到 bean 。

  • 示例:根据实现类的类型获取bean

  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public interface Happy {

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public class HappyImpl implements Happy {

}
  • HappyImpl2.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public class HappyImpl2 implements Happy {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="happy" class="com.github.fairy.era.bean.impl.HappyImpl"></bean>

    <bean id="happy2" class="com.github.fairy.era.bean.impl.HappyImpl2"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import com.github.fairy.era.bean.impl.HappyImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Happy happyImpl = context.getBean(HappyImpl.class);
        System.out.println("happyImpl = " + happyImpl);
    }
}
  • 结果:
happyImpl = com.github.fairy.era.bean.impl.HappyImpl@6c1a5b54
  • 示例:根据接口类型获取bean
  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public interface Happy {

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public class HappyImpl implements Happy {

}
  • HappyImpl2.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public class HappyImpl2 implements Happy {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="happy" class="com.github.fairy.era.bean.impl.HappyImpl"></bean>

    <bean id="happy2" class="com.github.fairy.era.bean.impl.HappyImpl2"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Happy happy = context.getBean(Happy.class);
        System.out.println("happy = " + happy);
    }
}
  • 结果:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.github.fairy.era.bean.Happy' available: expected single matching bean but found 2: happy,happy2

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1262)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
    at com.github.fairy.era.bean.SpringTest.test(SpringTest.java:22)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

2.4 情景四

  • 声明一个接口,接口有一个实现类,创建一个切面类,对上面接口中的实现类应用通知。
  • ① 根据接口类型获取可以获取到 bean 。
  • ② 根据实现类的类型不能获取到 bean ,因为应用了切面之后,真正放到 IOC 容器中的是代理类的对象,而不是目标类的对象。

  • 示例:根据接口类型获取获取 bean

  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public interface Happy {

    void add();

    void sub();

    void mul();

    void div();

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
@Component
public class HappyImpl implements Happy {

    @Override
    public void add() {
        System.out.println("add方法");
    }

    @Override
    public void sub() {
        System.out.println("sub方法");
    }

    @Override
    public void mul() {
        System.out.println("mul方法");
    }

    @Override
    public void div() {
        System.out.println("div方法");
    }
}
  • LogAspect.java
package com.github.fairy.era.bean.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:24
 */
@Aspect
@Component
public class LogAspect {

    @Before("execution(* *..*.*(..))")
    public void printBeforeLog() {
        System.out.println("前置通知");
    }

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.github.fairy.era"></context:component-scan>

    <!-- 开启AOP的注解支持 -->
    <aop:aspectj-autoproxy/>
</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {


    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        Happy happy = context.getBean(Happy.class);

        happy.add();
    }
}
  • 结果:
前置通知
add方法

情景四之示例一的结果.png

  • 示例:根据实现类获取 bean
  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
public interface Happy {

    void add();

    void sub();

    void mul();

    void div();

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:05
 */
@Component
public class HappyImpl implements Happy {

    @Override
    public void add() {
        System.out.println("add方法");
    }

    @Override
    public void sub() {
        System.out.println("sub方法");
    }

    @Override
    public void mul() {
        System.out.println("mul方法");
    }

    @Override
    public void div() {
        System.out.println("div方法");
    }
}
  • LogAspect.java
package com.github.fairy.era.bean.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:24
 */
@Aspect
@Component
public class LogAspect {

    @Before("execution(* *..*.*(..))")
    public void printBeforeLog() {
        System.out.println("前置通知");
    }

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.github.fairy.era"></context:component-scan>

    <!-- 开启AOP的注解支持 -->
    <aop:aspectj-autoproxy/>
</beans>
  • 测试:
package com.github.fairy.era.bean;

import com.github.fairy.era.bean.impl.HappyImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {


    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        Happy happy = context.getBean(HappyImpl.class);

        happy.add();
    }
}
  • 结果:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.github.fairy.era.bean.impl.HappyImpl' available

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
    at com.github.fairy.era.bean.SpringTest.test(SpringTest.java:20)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

2.5 情景五

  • 声明一个类,创建一个切面类,对这个类应用通知,根据类的类型可以获取到 bean 。

根据类型获取bean的情景五.png

  • 示例:
  • StudentService.java
package com.github.fairy.era.bean.service;

import org.springframework.stereotype.Service;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:53
 */
@Service
public class StudentService {

    public void getMessage() {
        System.out.println("getMessage");
    }
}
  • LogAspect.java
package com.github.fairy.era.bean.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:24
 */
@Aspect
@Component
public class LogAspect {

    @Before("execution(* *..*.*(..))")
    public void printBeforeLog() {
        System.out.println("前置通知");
    }

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.github.fairy.era"></context:component-scan>

    <!-- 开启AOP的注解支持 -->
    <aop:aspectj-autoproxy/>
</beans>
  • 测试:
package com.github.fairy.era.bean;

import com.github.fairy.era.bean.service.StudentService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        StudentService studentService = context.getBean(StudentService.class);

        studentService.getMessage();
    }
}
  • 结果:
前置通知
getMessage

根据类型获取bean的情景五的示例.png

第三章:自动装配

3.1 概述

  • 自动装配需要先从 IOC 容器中获取到唯一的一个 bean 才能够执行装配,所以装配是否成功和装配底层的原理和钱测试的获取 bean 的机制是一致的。

3.2 情景一

  • bean 对应的类没有实现任何接口,根据 bean 本身的类型装配这个 bean 。
  • ① 如果 IOC 容器中同类型的 bean 只有一个,那么正常装配。
  • ② 如果 IOC 容器中同类型的 bean 不止一个,那么 @Autowired 注解会根据 bean 的 id 和属性名匹配,如果匹配成功,那么就注入,否则抛出 NoUniqueBeanDefinitionException 异常。

  • 示例:IOC 容器中同类型的 bean 只有一个

  • Hello.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:24
 */
public class Hello {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="com.github.fairy.era.bean.Hello"/>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private Hello hello;

    @Test
    public void test() {
        System.out.println("hello = " + hello);
    }
}
  • 结果:
hello = com.github.fairy.era.bean.Hello@1722011b
  • 示例:IOC 容器中同类型的 bean 不止一个
  • Hello.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:24
 */
public class Hello {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="com.github.fairy.era.bean.Hello"/>
    <bean id="hello2" class="com.github.fairy.era.bean.Hello"/>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private Hello hello3;

    @Test
    public void test() {
        System.out.println("hello = " + hello3);
    }
}
  • 结果:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.github.fairy.era.bean.SpringTest': Unsatisfied dependency expressed through field 'hello3'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.github.fairy.era.bean.Hello' available: expected single matching bean but found 2: hello,hello2

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:417)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.github.fairy.era.bean.Hello' available: expected single matching bean but found 2: hello,hello2
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1358)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656)
    ... 29 more

3.3 情景二

  • 目标 bean 对应的类实现了接口,这个接口也只有这一个实现类。
  • ① 根据接口类型装配 bean ,成功。
  • ② 根据实现类的类型装配 bean ,成功。

  • 示例:根据接口类型装配 bean

  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public interface Happy {

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public class HappyImpl implements Happy {

}
  • applicatoinContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="happy" class="com.github.fairy.era.bean.impl.HappyImpl"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private Happy happy;

    @Test
    public void test() {
        System.out.println("happy = " + happy);
    }

}
  • 结果:
happy = com.github.fairy.era.bean.impl.HappyImpl@57ad2aa7
  • 示例:根据实现类类型装配 bean
  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public interface Happy {

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public class HappyImpl implements Happy {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="happy" class="com.github.fairy.era.bean.impl.HappyImpl"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import com.github.fairy.era.bean.impl.HappyImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private HappyImpl happyImpl;

    @Test
    public void test() {
        System.out.println("happyImpl = " + happyImpl);
    }

}
  • 结果:
happyImpl = com.github.fairy.era.bean.impl.HappyImpl@57ad2aa7

3.4 情景三

  • 声明一个接口,该接口有多个实现类,并且这多个实现类都放入到IOC容器中。
  • ① 根据接口类型装配 bean ,@Autowired 注解会先根据类型查找,此时会找到多个符合的 bean ,然后根据成员变量名作为 bean 的 id 进一步筛选,如果没有id匹配的,则会抛出 NoUniqueBeanDefinitionException 异常,表示 IOC 容器中这个类型的 bean 有多个。
  • ② 根据实现类的类型装配 bean,成功。

  • 示例:根据实现类的类型装配 bean

  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public interface Happy {

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public class HappyImpl implements Happy {

}
  • HappyImpl2.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public class HappyImpl2 implements Happy {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="happy" class="com.github.fairy.era.bean.impl.HappyImpl"></bean>
    <bean id="happy2" class="com.github.fairy.era.bean.impl.HappyImpl2"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import com.github.fairy.era.bean.impl.HappyImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private HappyImpl happyImpl;

    @Test
    public void test() {
        System.out.println("happyImpl = " + happyImpl);
    }

}
  • 结果:
happyImpl = com.github.fairy.era.bean.impl.HappyImpl@5b3f61ff
  • 示例:根据接口类型装配 bean
  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public interface Happy {

}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public class HappyImpl implements Happy {

}
  • HappyImpl2.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public class HappyImpl2 implements Happy {

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="happy" class="com.github.fairy.era.bean.impl.HappyImpl"></bean>
    <bean id="happy2" class="com.github.fairy.era.bean.impl.HappyImpl2"></bean>

</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private Happy happy;

    @Test
    public void test() {
        System.out.println("happy = " + happy);
    }

}
  • 结果:
happy = com.github.fairy.era.bean.impl.HappyImpl@5b3f61ff

3.5 情景四

  • 声明一个接口,该接口有一个实现类,创建一个切面类,对实现类应用通知。
  • ① 根据接口类型装配 bean,成功。
  • ② 根据实现类的类型装配 bean,会抛出 BeanNotOfRequiredTypeException 异常。

  • 示例:根据接口类型装配 bean

  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public interface Happy {
    void add();

    void sub();

    void mul();

    void div();
}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
@Component
public class HappyImpl implements Happy {
    @Override
    public void add() {
        System.out.println("add方法");
    }

    @Override
    public void sub() {
        System.out.println("sub方法");
    }

    @Override
    public void mul() {
        System.out.println("mul方法");
    }

    @Override
    public void div() {
        System.out.println("div方法");
    }
}
  • LogAspect.java
package com.github.fairy.era.bean.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:24
 */
@Aspect
@Component
public class LogAspect {

    @Before("execution(* *..*.*(..))")
    public void printBeforeLog() {
        System.out.println("前置通知");
    }

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.github.fairy.era"></context:component-scan>

    <!-- 开启AOP的注解支持 -->
    <aop:aspectj-autoproxy/>
</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private Happy happy;

    @Test
    public void test() {
        System.out.println("happy = " + happy);
    }

}
  • 结果:
前置通知
happy = com.github.fairy.era.bean.impl.HappyImpl@192d74fb
  • 示例:根据实现类的类型装配 bean
  • Happy.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
public interface Happy {
    void add();

    void sub();

    void mul();

    void div();
}
  • HappyImpl.java
package com.github.fairy.era.bean.impl;

import com.github.fairy.era.bean.Happy;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
@Component
public class HappyImpl implements Happy {
    @Override
    public void add() {
        System.out.println("add方法");
    }

    @Override
    public void sub() {
        System.out.println("sub方法");
    }

    @Override
    public void mul() {
        System.out.println("mul方法");
    }

    @Override
    public void div() {
        System.out.println("div方法");
    }
}
  • LogAspect.java
package com.github.fairy.era.bean.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:24
 */
@Aspect
@Component
public class LogAspect {

    @Before("execution(* *..*.*(..))")
    public void printBeforeLog() {
        System.out.println("前置通知");
    }

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.github.fairy.era"></context:component-scan>

    <!-- 开启AOP的注解支持 -->
    <aop:aspectj-autoproxy/>
</beans>
  • 测试:
package com.github.fairy.era.bean;

import com.github.fairy.era.bean.impl.HappyImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private HappyImpl happyImpl;

    @Test
    public void test() {
        System.out.println("happyImpl = " + happyImpl);
    }

}
  • 结果:
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'happyImpl' is expected to be of type 'com.github.fairy.era.bean.impl.HappyImpl' but was actually of type 'com.sun.proxy.$Proxy21'
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1809)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1786)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656)
    ... 29 more

3.6 情景五

  • 声明一个类,创建一个切面类,对这个类中应用通知,根据类装配 bean ,成功。

  • 示例:

  • Happy.java
package com.github.fairy.era.bean;

import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 09:51
 */
@Component
public class Happy {
    public void add() {
        System.out.println("add方法");
    }

    public void sub() {
        System.out.println("sub方法");
    }

    public void mul() {
        System.out.println("mul方法");
    }

    public void div() {
        System.out.println("div方法");
    }
}
  • LogAspect.java
package com.github.fairy.era.bean.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-09 08:24
 */
@Aspect
@Component
public class LogAspect {

    @Before("execution(* *..*.*(..))")
    public void printBeforeLog() {
        System.out.println("前置通知");
    }

}
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.github.fairy.era"></context:component-scan>

    <!-- 开启AOP的注解支持 -->
    <aop:aspectj-autoproxy/>
</beans>
  • 测试:
package com.github.fairy.era.bean;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class SpringTest {

    @Autowired
    private Happy happy;

    @Test
    public void test() {
        System.out.println("happy = " + happy);
    }

}
  • 结果:
前置通知
happy = com.github.fairy.era.bean.Happy@63c5efee

第四章:总结

4.1 对实现了接口的类应用切面

对实现了接口的类应用切面.png

4.2 对没实现接口的类应用切面

对没实现接口的类应用切面.png