Spring复习03----bean的作用域------ bean的自动装配-------Spring 注解实现自动装配--------Spring注解实现组件注册------注解属性赋值

参考

bean 的作用域

在这里插入图片描述
①The Singleton Scope
在这里插入图片描述

<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

②The Prototype Scope
在这里插入图片描述

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

bean 的自动装配

在Spring中有三种装配方式:
①在xml中显式地装配
②在java 显式地装配
③隐式地自动装配(重点)

1.byName 的自动装配

在这里插入图片描述

2.byType 的自动装配

在这里插入图片描述

Spring 注解实现自动装配

要使用注解需要知道:

  1. 导入约束 context
  2. 配置注解的支持
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

@Autowired

  • 默认按照类型去找对应得组件:applicationContext.getBean(BookDao.class);

  • 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找。applicationContext.getBean(“bookDao”);

  • 直接在属性上使用即可,也可以在set()方法,构造器,参数使用。 如果只有一个有参构造器,那么这个有参构造
    器的Autowired 可以省略,从容器中自动装配。

  • 使用@Autowired 我们可以不用有set()方法,但前提条件是自动装配的属性在ioc容器中已经存在,且符合byName规则。

  • 自动装配一定要将属性赋值好,@Autowired(”required=false“) 可以允许属性值为null.

  • @bean 标注的方法创建对象的时候,方法参数默认从容器中获取。

@Qulified(value=“xxxx”)
如果Autowired 自动装配的环境比较复杂,那么我们可以用这个来配合Autowired 来使用,确定唯一的bean 对象注入。

@Primary
让Spring 进行自动装配的时候,默认首选的bean,此时@Qulified(value=“xxxx”)不能同时使用了

拓展
@Nullable
字段标记了这个注解,说明这个注解可以为null.


Spring 还支持 @Resource 和@Inject

@Resource

  • 可以像@Autowired 一样自动装配,默认是按照属性的名称作为id去装配组件,@Resource(name=“xxxx”)来指定id去装配。
  • 不能支持@Primary 功能,也不支持@Autowired(”required=false“)

@Inject
需要导入javax.inject 依赖,和@Autowired功能一样,但不支持@Autowired(”required=false“)的注解。

Spring 注解实现-- 组件注册

@Configuration
告诉spring这是一个配置类,相当于xml方式中的 <beans> </beans>

@Bean
向容器中注册一个组件,类型默认是返回值类型,id默认是方法名作为id.

 @Bean
    public Person person(){
        return new Person("KKK", 25);
    }

@Bean(“person”) 指定bean 的id.

@ComponentScan //不写参数,则默认扫本类下的包及子包
@ComponentScan(“cn.fg2”) //jdk8支持写多个@ComponentScan,源码里面有个@Repeatable

@ComponentScan(value="cn.fg",includeFilters={  //包扫描 
		@Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
},excludeFilters={
		@Filter(type=FilterType.ANNOTATION,classes={Service.class})
},useDefaultFilters=false)

//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型  @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class})
//FilterType.CUSTOM:使用自定义规则


等同于

<context:component-scan base-package="cn.fg">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	<context:exinclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

自定义TypeFilter指定过滤规则

public class MyTypeFilter implements TypeFilter {
 
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();
        String className = classMetadata.getClassName();
        System.out.println("---" + className);
        /*if (className.contains("er")){
            return true;
        }*/
        return false;
    }
}

@Scope(“prototype”) 多例的bean,默认是多实例的bean

@Conditional(LinuxCondition.class)
必须满足条件后,bean才会被创建,该注解也可以用在类上


package cn.fg.demo.condition;
 
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
 
//判断是否linux系统
public class LinuxCondition implements Condition { //需要实现Condition接口
 
	/**
	 * ConditionContext:判断条件能使用的上下文(环境)
	 * AnnotatedTypeMetadata:注释信息,可以获取到注解标注在所在类的或所在方法上的其他注解的信息,这里传进来的是StandardAnnotationMetadata,应用场景搜百度
	 */
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO是否linux系统
		//1、能获取到ioc使用的beanfactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		//2、获取类加载器
		ClassLoader classLoader = context.getClassLoader();
		//3、获取当前环境信息
		Environment environment = context.getEnvironment();
		//4、获取到bean定义的注册类
		BeanDefinitionRegistry registry = context.getRegistry();
		
		String property = environment.getProperty("os.name");
		
		//可以判断容器中的bean注册情况,也可以给容器中注册bean
		boolean definition = registry.containsBeanDefinition("person");
		if(property.contains("linux")){
			return true;
		}
		
		return false;
	}

@Import给容器中快速导入组件

public class TestImport {
}
/**
 * 配置类,代替配置文件
 */
@Configuration  //告诉Spring这是一个配置类
@Import(TestImport.class)
public class MainConfig {
    @Bean("person")
    public Person person(){
        return new Person("KKK", 25);
    }
}

ImportSelector: 返回需要导入的组件的全类名数组。springBoot常用

public class MyImportSelector implements ImportSelector {
 
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.bjtu.bean.Blue","com.bjtu.bean.Red"};
    }
}
@Import({TestImport.class, MyImportSelector.class})
public class MainConfig {
    @Bean("person")
    public Person person(){
        return new Person("KKK", 25);
    }
}

在这里插入图片描述
ImportBeanDefinitionRegistrar:手动注册bean到容器中

//创建一个spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
    //返回一个Color对象,这个对象会添加到容器中
    @Override
    public Color getObject() throws Exception {
        System.out.println("ColorFactoryBean.....getObject....");
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }

    //是单例?
    //true,这个bean是个单实例,在容器中保存一份
    //false,多实例,每次获取都会创建一个新实例
    @Override
    public boolean isSingleton() {
        return false;
    }
}
@Test
public void ImportTest(){
    
    //工厂Bean获取的是调用getObject创建的对象
    //多实例的Bean每创建一次对象就调用一次getObject()方法
    Object bean1 = applicationContext.getBean("colorFactoryBean");
    Object bean2 = applicationContext.getBean("colorFactoryBean");
    System.out.println("bean1的类型是:"+bean1.getClass());
    System.out.println(bean1 == bean2);
    System.out.println("***********************");
    //加上“&”获取的就是获取工厂本身
    Object bean3 = applicationContext.getBean("&colorFactoryBean");
    System.out.println(bean3);
}

Spring 注解 属性赋值

@Value赋值
1). 基本数值
2). 可以使用SpEL:#{}
3). 可以写${},取出配置文件【properties】中的值(在运行环境变量里面的值)
注:对于idea来说,它的路径resourse默认到文件,所以只需要文件名就只可以获取到里面的值

public class Person {
    
    //1.基本数值
    @Value("张三")
    private String name;
    //2.SpEL:#{}
    @Value("#{18-2}")
    private Integer age;
    //取出配置文件properties中的值
    @Value("${person.nickName}")
    private String nickName;

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nickName='" + nickName + '\'' +
                '}';
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }
}
//使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中
//   加载完外部的配置文件以后使用${}取出配置文件的值
@PropertySource(value = {"person.properties"})
@Configuration  //声明配置类
public class MainConfigOfProperty {

    @Bean//注册一个组件
    public Person person(){
        return new Person();
    }
}
//测试方法
public class IocTestPropertyValue {
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProperty.class);


        printBean(applicationContext);

        System.out.println("-------------------------");

        Person person = (Person)applicationContext.getBean("person");
        System.out.println(person);

        //运行时的环境变量
        
        //这是第二种获得配置文件中的值的方式
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String property = environment.getProperty("person.nickName");
        System.out.println(property);

        //关闭容器
        applicationContext.close();
    }

    private void printBean(AnnotationConfigApplicationContext applicationContext){
        String[] names = applicationContext.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值