spring boot 三:2.组件添加-底层注解@Import导入组件
1 前言
除了@Configuration和@Bean增加组件的方式,spring常用的还有@Component、@Controller、@Service、@Repository注解,这些注解效果都用于增加组件,效果一致,只是@Component用于普通的pojo、domain类型的实体类,@Controller用于controller层,@Service用于服务层,@Repository用于数据库操作层,只作意义层面的区别,无实际效果差别。spring这些注解都可以用于springboot中,只是如果使用非xml,即全注解形式,那么包扫描,只需要在springboot的启动类上,增加如下扫描的包路径即可(不增加scanBasePackages参数,默认扫描该启动类所在的包路径下的全部类),就能自动扫描该路径下带有@Component、@Controller、@Service、@Repository注解的组件(也就带有这些注解的类):
@SpringBootApplication(scanBasePackages = {"com.xiaoxu"})
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
注意:故而springboot的启动类,一定要在src/main/java路径下,新建包,再将启动类放入该包下,如果启动类MainApplication文件直接放在src/main/java路径下,启动时会抛错提示。
@ComponentScan注解:spring使用该包扫描注解,根据该配置类,来找到@Component、@Controller、@Service、@Repository注解修饰的类,统一进行管理,比如以下的spring配置类用注解进行包扫描:
package com.xiaoxu.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //作为配置类,替代配置文件
@ComponentScan(basePackages = {"com.xiaoxu"})
public class SpringConfig {
}
所以,既可以把springboot的启动类,看作是主程序类,也可以看作是主配置类,效果如同spring的注解扫描配置类。
另外,针对@Bean注解,属性name和value是一个效果,一般来说,用了name,就不用了value,如果非要同时使用@Bean注解的name和value属性,name和value的值必须一致,如下(不一致也会抛错提示):
@Configuration(proxyBeanMethods = false)
public class MyConfig {
// @Bean(name = "fruit")
@Bean(name = "myfruit",value = "myfruit")
public Fruit getFruit() throws ParseException {
Fruit fruit = new Fruit();
fruit.setFname("桃子");
fruit.setPrice(new BigDecimal("12.5"));
fruit.setCount(120);
fruit.setDropDate(new Date());
return fruit;
}
}
@Bean的name或者value值,本质上就是spring的xml中,bean标签的id(class应该是通过反射来获取返回值的全限定类名的),如果不写name或者value,那么默认的id就是方法名,这个id,在springboot的启动类上下文SpringApplication.run(MainApplication.class, args);的返回值中,在调用getBean方法时需要使用,或者在调用如下时:
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
String[] beanDefinitionNames = run.getBeanDefinitionNames();
@Bean中的使用了name或者value,或者没有name和value值时,run.getBeanDefinitionNames()打印出的组件名中,可以找到该bean对应的组件名称,即id。
另外,主程序类的@SpringBootApplication(scanBasePackages = { " com.xiaoxu " })注解,作用相当于如下的三个注解:
@EnableAutoConfiguration
@ComponentScan
@SpringBootConfiguration
2 @Import注解
只要是springboot的组件上,都可以增加该注解(如自己定义的类,或者jar包引入三方的)
@Import({A.class,B.class}):
自动调用这些类的无参构造方法,创建组件:
tips:idea自动创建返回值,写完有返回值的语句后,按钮下ctrl+alt+v,即可自动生成返回值所定义的对象。
(0)自己定义的实体类(或者jar包中的类):
package com.xiaoxu.domain;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author xiaoxu
* @date 2021-12-15
* Ymybatis:com.xiaoxu.domain.User
*/
@Data
public class User {
//属性名和列名一样
private int id;
private String name;
private byte age;
private BigDecimal money;
@Override
public String toString() {
return "用户实体信息{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", money=" + money +
'}';
}
}
(1)在配置类上使用@Import:
package com.xiaoxu.config;
import com.xiaoxu.domain.Fruit;
import com.xiaoxu.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author xiaoxu
* @date 2021-12-27
* Ymybatis:com.xiaoxu.config.MyConfig
*/
@Import({User.class})
@Configuration(proxyBeanMethods = false)
public class MyConfig {
// @Bean(name = "fruit")
@Bean(name = "myfruit",value = "myfruit")
public Fruit getFruit() throws ParseException {
Fruit fruit = new Fruit();
fruit.setFname("桃子");
fruit.setPrice(new BigDecimal("12.5"));
fruit.setCount(120);
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(s.format(new Date()));
String d = s.format(new Date());
System.out.println(s.parse(d));
fruit.setDropDate(s.parse(d));
return fruit;
}
}
(2)主程序类打印,可看到User组件:
@SpringBootApplication(scanBasePackages = {"com.xiaoxu"})
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
String[] beanNamesForType = run.getBeanNamesForType(User.class);
System.out.println("*******开始*********");
for (String s : beanNamesForType) {
System.out.println(s);
}
System.out.println("*******结束*********");
}
}
*******开始*********
com.xiaoxu.domain.User
*******结束*********
可见,给容器中自动创建出了这些类型的组件,默认组件的名字(id)是全限定类名。