# 注解实现 IoC

将类的创建交给我们配置的 JavaConfig 类完成,Spring 只负责维护和管理,本质上就是把 XML 配置声明转移到 Java 配置类中。

因为创建交给 Java 代码,所以我们在类创建的时候可以执行更多的操作,纯 Java 代码,扩展性高,十分灵活。

创建一个配置类,添加 @Configuration 注解声明为注解类;在配置类中编写返回 Bean 对象的方法,加上 @Bean 注解,该实例创建后会交给 spring 管理:

@Configuration
public class MyConfiguration {
 
    @Bean
    @Scope("prototype")
    public Student student() {
        // 也可以是 @Bean ("xxxx")
        // 方法名建议与实例名相同(首字母小写)
        return new Student();
        // return new Student("name");
    }
}

创建出来的 Bean 对象还是默认单例模式,所以可以通过 @Scope 注解修改。

下面讲的其实就是注解配置,上面的是 Java 配置,最开始的是 xml 配置。

也可以删除这些 bean 方法,直接在类上面使用 @ComponentScan("包") 来自动扫描:

@ComponentScan("com.bean")
@Configuration
public class MyConfiguration {
 
}

在这种情况下, bean 类需要加上 @Component 才可以,配置类就是扫描给定包下面的 Component

@Component
@Scope("prototype")
@Setter
public class Student {
	// ....
}

其实可用的还有 @Controller@Service 等,他们和 @Component 是一样的,只不过在 MVC 架构下,不同 bean 承担不同角色,使用对应的注解可以提高可读性。

# 自动装配

  • @Resource 注解:

Student 类中有一个属性是 private Card card ,就可以在属性上使用该注解,Spring 就会自动注入(在容器中查找)

@Component
public class Student {
    // 不需要 set 方法
    @Resource
    Card card;
    
    /**
    也可以是:
    @Resource
    public void setCard (Card card) {
    	this.card = card;
    }
    */
}
  • @AutoWired 注解:

和上面那个一样的,但是不推荐使用在属性上,可以使用在构造方法,set 方法和方法参数上。

@ComponentScan("com.bean")
@Configuration
public class MainConfiguration {
    @Bean
    public Student student(@Autowired Card card){
        Student student = new Student();
        student.setCard(card);
        return student;
    }
}

之前通过 xml 配置,可以指定 init-methoddestroy ,这里可以使用 @PostConstruct@PreDestroy 注解。

# 注解实现 AOP

回忆之前 AOP 的内容,主要是切点,切面,通知。

  • 开启 AOP 注解,需要在配置类加上 @EnableAspectJAutoProxy :
@EnableAspectJAutoProxy
public class MainConfiguration {
    
}
  • 还是在 Student 类找切入点,假设是 study 方法
@Data
@Component
public class Student {
	// ...
    public void study() {
        System.out.println(name + " is studying...");
    }
}
  • 定义切面类,这点是和 xml 配置一样的(只是里面的方法,也就是通知需要加上注解)。我们需要这么一个类,因为 AOP 就是将分散在各个业务逻辑代码中相同的代码通过横向切割的方式抽取到一个独立的模块中!
@Component
@Aspect
public class AopTest {
    @Before("execution(* com.bean.Student.study())")
    public void before() {
        System.out.println("Student.study()前置通知");
    }
    
    // 也可以加上 JoinPoint
    @After("execution(* com.bean.Student.study())")
    public void after(JoinPoint point) {
        System.out.println("切点方法参数列表:" + Arrays.toString(point.getArgs()));
        System.out.println("Student.study()后置通知");
    }
}

# 参考

https://pdai.tech/md/spring/spring-x-framework-ioc.html#java - 配置

https://www.yuque.com/qingkongxiaguang/spring/rlgcf7#fdba2fec