Spring注解开发之组件注册(一)

Spring注解开发

Spring注解开发之组件注册下半篇

IOC,中文名为控制反转,是将Java的bean对象存储在容器中,当需要使用时,通过名字获取该对象。而不是通过new关键字去创建。

1.@Configuration & @Bean给容器中注册组件

第一种:

beans.xml:

启动类:

通过beans.xml获取bean

	      ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		  Person person = (People) applicationContext.getBean("person");
		  System.out.println(bean);

第二种:

通过注解来注册组件(@Bean(”person“)可以设定id名)

在这里插入图片描述

启动类:

通过配置类 注解

		 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
		 application.getBean(Person.class)
         System.out.println(bean);

2.@ComponentScan 自动扫描组件

XML中配置

 // 包扫描,只要标注了@Controller、@Service、@Reposity、@Component	 
 <context:component-scan base-package="com.atguigu"></context:component-scan>

通过注解开发

只需要配置包扫描 @ComponentScan(value = “com.atguigu”)

// 指定扫描规则  
// excludeFilters = Filter[]  指定扫描的时候按照什么规则排除那些组件
// includeFilters = Filter[]  指定扫描的时候只需要包含那些组件
// useDefaultFilters = false  关闭全部扫描   默认为true  
@ComponentScan(value = "com.atguigu",excludeFilters = {
         @Filter(type = FilterType.ANNOTATION,classes = {Controller.class})@Filter(type = FilterType.ANNOTATION,classes = {UserService.class})@Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
         },useDefaultFilters = false )
 
// 可以多配置几个 
@ComponentScans(
		value = {
		       @ComponentScan(value = "com.atguigu",excludeFilters = {
                            @Filter(type = FilterType.ANNOTATION,classes =                             {Controller.class})
                   },useDefaultFilters = false)
		}
)
 //FilterType.ANNOTATION  按照注释
 //FilterType.ASSINGABLE_TYPE  按照给定的类型,实现类和子类
 //FilterType.ASPECTJ  使用ASPECTJ表达式
 //FilterType.REGEX  使用正则指定
 //FilterType.CUSTOM  使用自定义规则

自定义TypeFilter指定过滤规则

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
 
import java.io.IOException;
 
public class MyTypeFilter implements TypeFilter {
 
    /**
     * metadataReader:读取到的当前正在扫描的类的信息
     * metadataReaderFactory:可以获取到其他任何类信息的
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        // TODO Auto-generated method stub
        //获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();
 
        String className = classMetadata.getClassName();
        System.out.println("--->"+className);
        if(className.contains("ll")){   // 扫描到了
            return true;  
        }
        return false;
    }
}

3.@Scope 设置组件作用域

在IOC容器里面默认bean都是单实例的

​ Scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对象进入其相应的scope之前生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。

@Scope注解有四种作用域,即

  1. SINGLETON:单例模式,默认模式,不写的时候默认是SINGLETON

    ​ ioc容器启动的时候就已经创建了person实例,在Spring的IOC容器从创建到退出都只会存在一个实例,所有对该对象的引用将共享这个实例。以后每次获取都是直接从容器中取(map.get())

  2. PROTOTYPE:原型模式 多实例 ioc启动时并不会去创建person实例,而是每次获取的时候才会调用方法创建对象

  3. REQUEST:同一次请求则只创建一次实例

  4. SESSION:同一个session只创建一次实例

懒加载 :

​ 单实例bean,默认在容器启动的时候创建对象

​ 懒加载,容器启动的时候先不创建对象。第一次获取Bean创建对象并初始化
在这里插入图片描述

4.@Conditional 按照条件注册bean

@Conditional 按照一定的条件进行判断,满足条件给容器中注册bean

@Conditional源码
    
    @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

    // 传入一个Condition数组
    Class<? extends Condition>[] value();

}
Condition接口源码:

@FunctionalInterface
public interface Condition {

    /**
     * ConditionContext:判断条件能使用的上下文环境
     * AnnotatedTypeMetadata:注释信息
     */
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

业务场景

如果是linux系统则注册linus,如果是windows系统则注册bill Gates

// 编写windows条件,需要实现接口Condition,重写matches方法
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 判断是否是Windows系统
        // 1. 获取到IOC使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 2. 获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        // 3. 获取运行环境
        Environment environment = context.getEnvironment();
        // 4. 获取到bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();

        // 容器中是否包含person,判断容器中的bean注册情况,也可以给容器中注册bean
        boolean person = registry.containsBeanDefinition("person");

        // 运行环境是否是Windows
        String property = environment.getProperty("os.name");
        assert property != null;
        return property.contains("Windows");
    }
}


// 编写linux系统
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        assert property != null;
        return property.contains("linux");
    }
}

// 编写配置类
@Configuration // 告诉Spring这是一个配置类
@ComponentScan(value = "com.lv")
public class MainConfig3 {

    @Bean("bill")
    @Conditional({WindowsCondition.class})
    public Person person() {
        return new Person("bill gates", 62);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person2() {
        return new Person("linus", 48);
    }
}

// 测试
@Test
public void test3() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
    Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);
    System.out.println(beansOfType);
}

Spring注解开发之组件注册下半篇

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓风残月Lx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值