1.spring组件学习:bean、ComponentScan、scope、lazy

自己在对spring学习时的一个记录,方便自己后面查阅。

1.spring的组件,在项目中使用了很久的spring,但是对spring中的一些组件不是很熟悉,下面一个一个的记录

一、bean

在基于spring的应用中,应用对象生存于spring容器中;spring容器负责创建对象,装配它们,配置它们,并管理它们的整个生命周期。以上描述的对象就是bean。

spring的常用配置bean的几种方式:

1、xml配置文件中《bean》配置,以前使用SSM时,比较流行的配置方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="worker" class="com.wuml.Worker">
        <property name="name" value="wuml"/>
        <property name="sex" value="18"/>
    </bean>
</beans>
package com.wuml;

import lombok.Data;

/**
 * @author by wml on 2019/10/16.
 */
@Data
public class Worker {
    private String name;
    private String sex;
}
package com.wuml;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author wml
 */
public class App 
{
    public static void main( String[] args )
    {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Worker worker = (Worker)classPathXmlApplicationContext.getBean("worker");
        System.out.println( worker.toString());
    }
}

理解:以上为通过xml配置方式获取到bean的方式,实际项目中是不会这样获取的,仅仅作为理解使用。

2、注解方式;现在比较主流的方式,不管是SSM还是spring boot基本都是使用这个方式。

package com.wuml;

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

/**
 * @author by wml on 2019/10/16.
 */
@Configuration
public class BeanConfig {

    @Bean("workerBean")
    public Worker worker(){
        Worker worker = new Worker();
        worker.setName("123");
        worker.setSex("18");
        return worker;
    }
}
package com.wuml;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author wml
 */
public class App 
{
    public static void main( String[] args )
    {
        //ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        ApplicationContext ApplicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);

        Worker worker = (Worker)ApplicationContext.getBean("workerBean");
        System.out.println( worker.toString());

    }
}

理解:在beanConfig中,@bean注解后面没有定义bean的名字时,在使用getBean获取bean时,默认就会通过方法名去获取bean(通过getBean(worker)去获取)

二、Configuration ComponentScan

@Configuration

用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

@ComponentScan

用于定义扫描类路径和扫描规则;

应用:当设置value或者basePackages属性时,在容器启动时,只会扫描该配置下的bean;

ComponentScan中includeFilters大意为,不采用默认的filter,使用自己配置的filter,includeFilters中常用的配置类型:annotation(注解,classes就对应注解类),CUSTOM(自定义filter)自定义的filter类需要实现TypeFilter接口,重写他的match方法,方法返回true时,会将该bean注入至容器中;

在使用includeFilters时,需要注意一点的是,在自己添加了Filter时,要将ComponentScan中useDefaultFilters属性设置为false,否则你的filter会不生效,因为在源码中ComponentScan是设置的true,大意就是会默认扫描component,controller,service,repository等注解修饰的类

/**
	 * Indicates whether automatic detection of classes annotated with {@code @Component}
	 * {@code @Repository}, {@code @Service}, or {@code @Controller} should be enabled.
	 */
	boolean useDefaultFilters() default true;

自定义的扫描规则描述:

FilterType.ANNOTATION:按照注解 :Controller.class

FilterType.ASSIGNABLE_TYPE:按照给定的类型;***.calss

FilterType.ASPECTJ:使用ASPECTJ表达式

FilterType.REGEX:正则指定

FilterType.CUSTOM:使用自定义规则,新建一个实现TypeFilter接口的类

package com.wuml.filter;

import org.springframework.core.io.Resource;
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;

/**
 * @author by wml on 2019/10/16.
 */
public class ClassFilter implements TypeFilter{
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //得到类的注解信息 metadataReader.getAnnotationMetadata();
        //得到类信息  metadataReader.getClassMetadata();
        //得到类路径
        Resource resource = metadataReader.getResource();
        //自己定义一个扫描规则 当我的类名字是包含Worker才OK
        if(resource.getFilename().contains("Worker")){
            return true;
        }
        return false;
    }
}
/**
 * @author by wml on 2019/10/16.
 */
@Configuration
@ComponentScan(includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM,value = ClassFilter.class),
},useDefaultFilters = false)
public class BeanScanConfig {

}

三、scope(面试中常问到的:Spring支持的bean的作用域

@Scope 通常情况下指定该bean会是单实例还是多实例,默认是单实例:singleton

单实例(singleton):当容器启动时,会调用方法来创建这个bean并放到容器中,后面每次使用这个bean时都是从容器中去拿相同的bean。

多实例(protoType):当bean被调用时才会创建一个新的实例,每个实例是不同的,即在内存中分配的地址是不同的;

还有几种不常用的作用域

request:针对在web应用中,提交一次请求就创建一个bean实例;

session:相同的session创建一个实例。

package com.wuml.scope;

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

/**
 * @author by wml on 2019/10/17.
 */
@Configuration
public class ScopeConfig {

    @Bean("scopeWorker1")
    public ScopeWorker1 getWorker(){
        return new ScopeWorker1("123","18");
    }

    @Scope(value = "prototype")
    @Bean
    public ScopeWorker2 scopeWorker2(){
        return new ScopeWorker2("123","18");
    }
}
package com.wuml;

import com.wuml.scope.ScopeConfig;
import com.wuml.scope.ScopeWorker2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author by wml on 2019/10/17.
 */
public class ScopeMainTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScopeConfig.class);

        Object scopeWoker10 = applicationContext.getBean("scopeWorker1");
        Object scopeWoker11 = applicationContext.getBean("scopeWorker1");
        ScopeWorker2 scopeWoker20 =(ScopeWorker2)applicationContext.getBean("scopeWorker2");
        ScopeWorker2 scopeWoker21 =(ScopeWorker2)applicationContext.getBean("scopeWorker2");
        System.out.println(scopeWoker10==scopeWoker11);
        System.out.println(scopeWoker20==scopeWoker21);
    }
}

运行结果:

四、Lazy

@Lazy 懒加载 个人理解懒汉加载 主要针对是单实例bean;

bean添加了Lazy注解后,该bean会在对象被使用时才会创建,容器初始化时不会创建该bean;

码地址:https://github.com/wuml-cruder/springTest(地址中的部分类被我移动位置,更加清楚)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值