配置组件
@ComponentScan(value = “com.example.demo”)
加载指定包,默认加载@Component、@Controller、@Service、@Repository
includeFilters
限定加载范围
@ComponentScan(
value = "com.example.demo",
includeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = {Service.class}), // 只加载@Service
useDefaultFilters = false) // useDefaultFilters 必须设置成false,否则Filter不生效,默认加载所有。
includeFilters.type
type = FilterType.ANNOTATION,classes = {Service.class} //按注解(@Service)过滤
type = FilterType.ASSIGNABLE_TYPE,classes = {xxx.class} //按指定类(xxx.class)过滤
type = FilterType.CUSTOM, classes = {MyTypeFilter.class} //按自定义的filter过滤
自定义filter过滤
public class MyTypeFilter implements TypeFilter {
/**
* @param metadataReader 获取当前操作类的信息,源信息(metadata)
* @param metadataReaderFactory 获取上下文信息
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
metadataReader.getAnnotationMetadata(); //获取扫描到的类注解信息
ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取扫描到的类信息
String className = classMetadata.getClassName();
System.out.println("--------------"+className);
if(className.contains("Person")){
return true;
}
return false;
}
}
@Configuration + @Bean
@Configuration
@ComponentScan(value = "com.example.demo.configuration")
public class MyConfig {
@Bean
public Person person(){ // 默认方法名为对象名,返回的对象默认单例
return new Person("xujj", 18);
}
@Bean(name="person1") //自定义对象名 : person1
}
@Scope
@Scope("prototype") // 原型模式
@Configuration
public class MyConfig {
@Bean
public Person person(){
return new Person("xujj", 18);
}
}
@Scope() 默认单例
@Scope(“singelton”) 单例模式,即每次调用返回同一个实例
@Scope(“prototype”) 原型模式,即每次调用返回一个新的实例
@Scope(“request”) 每次请求创建一个实例(主要应用于web
@Scope(“session”) 同一session只创建一个实例(主要应用于web)
验证Bean是否单例:
public class MyTest {
@Test
public void test() {
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
Object bean1 = app.getBean("person");
Object bean2 = app.getBean("person");
System.out.println(bean1 == bean2);
}
}
@Lazy
延迟加载,默认true,容器启动时,不创建对象,对象调用时才创建。
懒加载只针对单例Bean起作用
不添加@Lazy,启动时加载bean
@Configuration
public class MyConfig {
@Bean
public Person person(){
System.out.println("将对象添加到IoC容器中");
return new Person("Tom",18);
}
}
public class MyTest {
@Test
public void test(){
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
System.out.println("IoC容器创建完成");
app.getBean("person");
}
}
输出结果:
将对象添加到IoC容器中
IoC容器创建完成
添加 @Lazy
@Configuration
public class MyConfig {
@Lazy
@Bean
public Person person(){
System.out.println("将对象添加到IoC容器中");
return new Person("Tom",18);
}
}
输出结果:
IoC容器创建完成
将对象添加到IoC容器中
@Conditional
满足条件则注册、装载,spring4开始提供。
根据不同的系统,实例化不同的对象。
可通过修改VM参数:-ea Dos.name=Linux,来尝试Linux系统的情况。
@Configuration
public class MyConfig {
@Conditional(WinCondition.class) //判断条件
@Bean
public Person tom(){
System.out.println("将对象Tom添加到IoC容器中");
return new Person("Tom",18);
}
@Conditional(LinuxCondition.class)
@Bean
public Person lily(){
System.out.println("将对象lily添加到IoC容器中");
return new Person("lily",17);
}
}
public class WinCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//从IoC容器中拿到已经实例化的对象
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //bean工厂
Environment environment = context.getEnvironment(); //环境变量
String osName = environment.getProperty("os.name");
if(osName.contains("Windows")){
return true;
}
return false;
}
}
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//从IoC容器中拿到已经实例化的对象
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Environment environment = context.getEnvironment();
String osName = environment.getProperty("os.name");
System.out.println(osName);
if(osName.contains("Linux")){
return true;
}
return false;
}
}
条件控制
并不是所有的插件都遵循spring.factories规则。比如 RedisAutoConfiguration类,基于@ConditionalOnClass({RedisOperations.class})条件控制,装载redis的配置。
spring-autoconfigure-metadata.properties 文件
resources\META-INF目录下创建该文件,表示如果引用的上层项目中存在com.gupaoedu.DemoClass该类,则加载当前项目中类。
文件内容:
com.gupaoedu.autoconfiguration.demo.GupaoConfiguration.ConditionalOnClass=com.gupaoedu.DemoClass
@Import
直接导入:
@Configuration
@Import(value = {Cat.class}) //直接导入 Cat.class
public class MyConfig {
}
自定义规则导入:实现 ImportSelector 接口
@Configuration
@Import(value = {MyImportSelector.class})
public class MyConfig {
}
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.gupaoedu.project.entity.Company",
"com.gupaoedu.project.entity.Member"}; // 传入需要导入的配置类、或者bean
}
}
手动注入:实现ImportBeanDefinitionRegistrar 接口
@Import(value = {MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 当前类的注解信息
* @param registry 完成BeanDefinition的注册
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean company = registry.containsBeanDefinition("com.gupaoedu.project.entity.Company");
boolean member = registry.containsBeanDefinition("com.gupaoedu.project.entity.Member");
if(company && member){
BeanDefinition beanDefinition = new RootBeanDefinition(User.class);
registry.registerBeanDefinition("user", beanDefinition);
}
}
}
通过FactoryBean注入:实现 FactoryBean 接口
@Configuration
public class MyConfig {
@Bean
public MyFactoryBean monkey(){
return new MyFactoryBean();
}
}
public class MyFactoryBean implements FactoryBean<Monkey> {
@Nullable
@Override
public Monkey getObject() throws Exception {
return new Monkey();
}
@Nullable
@Override
public Class<?> getObjectType() {
return Monkey.class;
}
@Override
public boolean isSingleton() {
return true; // true:单例,false:非单例
}
}
通过 isSingleton() 控制是否单例
测试类:
public class MyTest {
@Test
public void test(){
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
//通过FactoryBean注入的值
System.out.println("============" + app.getBean("monkey").getClass());
Object monkey1 = app.getBean("monkey");
Object monkey2 = app.getBean("monkey");
System.out.println("是否单例:" + monkey1 == monkey2);
//拿到构建monkey的FactoryBean
Object monkeyFactoryBean = app.getBean("&monkey");
System.out.println(monkeyFactoryBean);
String [] beanNames = app.getBeanDefinitionNames();
System.out.println(Arrays.toString(beanNames).replaceAll("\\[|\\]","").replaceAll(", ","\n"));
}
}
注意:app.getBean("&monkey") 获取 MyFactoryBean 的实例