自己在对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(地址中的部分类被我移动位置,更加清楚)