@Import的用法

官方定义:

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core

Using the @ImportAnnotation

Much as the <import/> element is used within Spring XML files to aid in modularizing 
configurations, the @Import annotation allows for loading @Bean definitions from another 
configuration class, as the following example shows:

@Import注解的作用与Spring的XML配置文件中的元素一样:都是用于帮助建立模块化配置,@Import可以从其他配置类中加载 @Bean的定义,如下所示:

@Configuration
public class ConfigA {

    @Bean
    public A a() {
        return new A();
    }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {

    @Bean
    public B b() {
        return new B();
    }
}
Now, rather than needing to specify both ConfigA.class and ConfigB.class when instantiating the 
context, only ConfigB needs to be supplied explicitly, as the following example shows:

如上代码,在类ConfigB中添加了注解 @Import(ConfigA.class) ,那么,在初始化上下文(如下所示)时就不需要同时指定类 ConfigA.class 和 类ConfigB.class 了,只需要显示的指定类 ConfigB即可,下面是例子:

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);

    // now both beans A and B will be available...
    A a = ctx.getBean(A.class);
    B b = ctx.getBean(B.class);
}

如上,初始化上下文ctx时只需要使用ConfigB,同样可以通过 ctx.getBean(A.class)获取在ConfigA中配置的A实例(bean)

This approach simplifies container instantiation, as only one class 
needs to be dealt with, rather than requiring you to remember a 
potentially large number of @Configuration classes during construction.

这种方法简化了容器的初始化,在初始化构造时,只需要处理一个类,而不必记住潜在的大量的@Configuration配置类。

小结: 以上是针对通过:

 ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);

这种方式获取bean实例时

A a = ctx.getBean(A.class);
    B b = ctx.getBean(B.class);

通过@Import注解时,可以简化容器的初始化!

但是,如果直接通过@Autowired注入的方式获取容器中的bean,@Import还有用武之地吗?

因为只要容器中有对应的bean存在,@Autowired就会将其注入过来!既然这样,那@Import似乎没有什么作用了!, 如下示例:

package com.xl.test.logtest.utils;

public class Pen {
	
	private String name = "this is apple!";
	
	public Pen () {
		System.out.println("+++constructing pen object+++");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
package com.xl.test.logtest.utils;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Eraser {
	
	@Bean
	public Pen genPenBean() {
		return new Pen();
	}
	
}

以上代码,在容器启动时会初始化一个Pen对象/实例/bean

package com.xl.test.logtest.utils;

public class Apple {
	
	private String name = "this is apple!";
	
	public Apple() {
		System.out.println("***constructing Apple object***");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
package com.xl.test.logtest.utils;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Tree {
	
	@Bean
	public Apple genAppleBean() {
		return new Apple();
	}
	
}

以上代码,在容器启动时会初始化一个Apple对象/实例/bean

编写测试类:
通过@Autowired直接获取想要的bean

package com.xl.test.logtest.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xl.test.logtest.utils.Apple;
import com.xl.test.logtest.utils.Pen;

@RestController
public class LogTestController {
	
	private static Logger logger = LoggerFactory.getLogger(LogTestController.class);
	
	@Autowired
	Pen pen;
	
	@Autowired
	Apple apple;
	
	@GetMapping("/log")
	public String log() {
		Assert.notNull(pen, "对象为空!");
		Assert.notNull(apple, "对象为空!");
		return "pen : "+ pen.getName()+ " ; apple: "+apple.getName();
	}
}

启动项目:完成bean的创建
在这里插入图片描述
浏览器访问,验证:
@Import的用法_第1张图片

断言Assert 并没有抛出异常信息,说明pen和apple对象都不为null,同时浏览器也输出了pen和apple的名字。

给类Eraser加上@Import(Tree.class)或者给类Tree加上@Import(Eraser.class),项目运行情况和测试结果没有任何变化!@Import注解没有起作用!验证略。

实际上,针对@Autowired注解的场景不是没有用,而是@Import是有它特定的使用场景的:@Import可以引入外部的bean。

何为外部的bean??

外部bean指的是:Spring容器启动时不会自动扫描的类并生成的bean。

Spring容器启动时会去扫描哪些类? : 主启动类所在包及子包下面的带有@Component注解的类!

而@Import注解就是用于引入外部的bean的, 示例如下:

在外部新建一个类Paper,如下:
@Import的用法_第2张图片

package com.other.pkg;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.xl.test.logtest.utils.Color;
import com.xl.test.logtest.utils.Picture;

@Configuration
public class Paper {

	@Bean
	public Color getColorBean() {
		System.out.println("********************color bean init********************");
		return new Color();
	}
	
	@Bean 
	public Picture getPictureBean() {
		System.out.println("********************picture bean init********************");
		return new Picture();
	}
	
}

在不使用@Import注解时,在测试类中注入外部类Paper中的bean :

package com.xl.test.logtest.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.other.pkg.Paper;
import com.xl.test.logtest.utils.Apple;
import com.xl.test.logtest.utils.Color;
import com.xl.test.logtest.utils.Pen;
import com.xl.test.logtest.utils.Picture;

@RestController
public class LogTestController {
	
	private static Logger logger = LoggerFactory.getLogger(LogTestController.class);
	
	@Autowired
	Paper paper;
	
	@Autowired
	Color color;
	
	@Autowired
	Picture picture;
	
	@GetMapping("/log")
	public String log() {
		return "paper : "+ paper+ " ; color: "+color.getName()+" ; picture: "+picture.getSize();
	}
	
	
}

启动项目,观察:
@Import的用法_第3张图片

在主启动类的包或子包下新建一个带@Component的类,同时,加上@Import注解:

package com.xl.test.logtest.utils;

import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import com.other.pkg.Paper;

@Import(Paper.class)
@Component
public class ForImport {

}

启动项目,测试:

@Import的用法_第4张图片

如上所示,项目启动成功,并完成外部类中相关bean的初始化; 访问项目再次测试:
@Import的用法_第5张图片

同样,获取到了外部类中的bean。

你可能感兴趣的:(#,spring笔记,spring,Import注解)