Spring基础(一)常用配置

Bean

Spring 框架的核心是容器。在基于 Spring 的应用中,应用对象生存于 Spring 容器中。Spring 容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡(可能就是 new 到 finalize());

Spring 容器并不是只有一个。Spring 自带了多个容器实现,可以归为两种不同的类型:

  1. bean 工厂(org.springframework.beans.factory.BeanFactory 接口定义):是最简单的容器,提供基本的 DI 支持;
  2. 应用上下文(org.springframework.context.ApplicationContext 接口定义):基于 BeanFactory 构建,并提供应用框架级别的服务,例如从属性文件解析文本信息以及发布应用事件给感兴趣的事件监听者;

bean 工厂对大多数应用来说往往太低级了,因此,应用上下文要比 bean 工厂更受欢迎;

应用上下文

Spring 自带了多种类型的应用上下文:

  • AnnotationConfigApplicationContext:从一个或多个基于 Java 的配置类中加载 Spring 应用上下文;
  • AnnotationConfigWebApplicationContext:从一个或多个基于 Java 的配置类中加载 Spring Web 应用上下文;
  • ClassPathXmlApplicationContext:从类路径下的一个或多个 XML 配置文件中加载上下文定义,把应用上下文的定义文件作为类资源;
  • FileSystemXmlApplicationContext:从文件系统下的一个或多个 XML 配置文件中加载上下文定义;
  • XmlWebApplicationContext:从 Web 应用下的一个或多个 XML 配置文件中加载上下文定义;

FileSystemXmlApplicationContext 示例:

//在指定的文件系统路径下查找 knight.xml 文件
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("c:/knight.xml");

ClassPathXmlApplicationContext 示例:

//在所有的类路径(包含 JAR 文件)下查找 knight.xml 文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("knight.xml");

从Java 配置中加载应用上下文,使用 AnnotationConfigApplicationContext 示例:

//通过一个配置类加载 bean
ApplicationContext context = new AnnotationConfigApplicationContext(包名.类名);

应用上下文准备就绪之后,就可以调用上下文的 getBean() 方法从 Spring 容器中获取 bean;

bean 的生命周期

  1. Spring 对 bean 进行实例化;
  2. Spring 将值和 bean 的引用注入到 bean 对应的属性中;
  3. 如果 bean 实现了 BeanNameAware 接口,Spring 将 bean 的 ID 传递给 setBeanName()方法;
  4. 如果 bean 实现了 BeanFactoryAware 接口,Spring 将调用 setBeanFactory()方法,将 BeanFactory 容器实例传入;
  5. 如果 bean 实现了 ApplicationContextAware 接口,Spring 将调用setApplicationContext() 方法,将 bean 所在的应用上下文的引用传入进来;
  6. 如果 bean 实现了 BeanPostProcessor 接口,Spring 将调用它们的 postProcessBeforeInitialization()方法;
  7. 如果 bean 实现了 InitializingBean 接口,Spring 将调用它们的 afterPropertiesSet()方法,如果 bean 使用 init-method 声明了初始化方法,该方法也会被调用;
  8. 如果 bean 实现了 BeanPostProcessor 接口,Spring 将调用它们的 postProcessAfterInitialization()方法;
  9. 此时,bean 已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
  10. 如果 bean 实现了 DisposableBean 接口,Spring 将调用它的 destory()接口方法。同样,如果 bean 使用 destory-method 声明了销毁方法,该方法也会被调用;

Bean的Scope

Scope描述的是Spring容器如何新建Bean的实例的。Spring的Scope有以下几种,通过@Scope注解来实现:

  • Singleton:一个Spring容器中只要一个Bean的实例,此为默认配置,全容器共享一个实例。
  • Prototype:每次调用新建一个Bean实例。
  • Request:Web项目中,给每一个http request新建一个Bean实例。
  • Session:Web项目中,给每一个http session新建一个Bean实例。

DemoSingletonService.java

@Service
public class DemoSingletonService {   //默认为Singleton,相当于@Scope("singleton")。
}

DemoPrototypeService.java

@Service
@Scope("prototype")
public class DemoPrototypeService {
}

ScopeConfig.java

@Configuration
@ComponentScan("扫描的包")
public class ScopeConfig {
}

TestScope.java

public class TestScope{
public static void main(String[] args){
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScopeConfig.class);
	DemoSingletonService s1 = context.getBean(DemoSingletonService.class);
	DemoSingletonService s2 = context.getBean(DemoSingletonService.class);
	DemoPrototypeService p1 = context.getBean(DemoPrototypeService.class);
	DemoPrototypeService p2 = context.getBean(DemoPrototypeService.class);
	System.out.println("s1与s2是否相等:"+s1.equals(s2));
	System.out.println("p1与p2是否相等:"+p1.equals(p2));
}
}

这里写图片描述

Spring EL和资源调用

Spring 开发中经常涉及调用各种资源的情况,包括普通文件、网址、配置文件、系统环境变量等,我们可以使用Spring 的表达式语言实现资源的注入。
Spring 主要在注解@Value的参数中使用表达式。
test.properties

book.author=yangdong
book.name=spring boot

DemoService.java

@Service
public class DemoService {
@Value("其他类的属性")
private String another;

public String getAnother() {
	return another;
}

public void setAnother(String another) {
	this.another = another;
}

}

test.txt

this is a test of @Value.

SpringEL.java

@Configuration
@ComponentScan("test")
@PropertySource("test/test.properties")  //注入配置文件
public class SpringEL{
    //注入普通字符串
	@Value("I Love you")
	private String normal;
	
	//注入操作系统属性
	@Value("#{systemProperties['os.name']}")
	private String osName;
	
	//注入表达式结果
	@Value("#{T(java.lang.Math).random() * 100.0}")
	private double randomNumber;
	
	//注入其他Bean属性
	@Value("#{demoService.another}")
	private String fromAnother;
	
	//注入文件资源
	@Value("classpath:test/test.txt")
	private Resource testFile;
	
	//注入网址资源
	@Value("http://www.baidu.com")
	private Resource testUrl;	
	
	/**
	 * 注入配置文件(注入配置文件 需要使用@PropertySource指定文件地址,若使用@Value注入,则要配置一个
	 * PropertySourcesPlaceholderConfigurer的Bean.
	 * 注入Properties还可以从Environment中获得。
	 */
	@Value("${book.name}")
	private String bookName;
	
	//注入Properties还可以从Environment中获得
	@Autowired
	private Environment environment;
	
	@Bean
	public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
	{
		return new PropertySourcesPlaceholderConfigurer();
	}
	
	public void outputResource() throws IOException
	{
		System.out.println(normal);
		System.out.println(osName);
		System.out.println(randomNumber);
		System.out.println(fromAnother);
		System.out.println(IOUtils.toString(testFile.getInputStream()));
		System.out.println(IOUtils.toString(testUrl.getInputStream()));
		System.out.println(bookName);
		System.out.println(environment.getProperty("book.author"));		
	}
		
}

TestSpringEL.java

public class TestSpringEL{
public static void main(String[] args){
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringEL.class);
	SpringEL el = context.getBean(SpringEL.class);
	el.outputResource();
	context.close();
}
}

这里写图片描述

Bean的初始化和销毁

实际开发的时候,经常会遇到在Bean使用之前或之后做些必要的操作,Spring对Bean的生命周期的操作提供了支持。在使用Java配置和注解配置下提供了如下两种方式:

  • Java配置方式:使用@Bean的initMethod 和 destroyMethod;
  • 注解方式:JSR-250的@PostConstruct 和 @PreDestroy;

BeanWay.java

public class BeanWay {	
public void init() 
{
	System.out.println("@Bean-init-method");
}

public  BeanWay() 
{
	super();
	System.out.println("初始化构造函数-BeanWay");
}

public void destroy() 
{
	System.out.println("@Bean-destroy-method");
}
}

JSR250Way.java

public class JSR250Way {
@PostConstruct   //在构造函数执行完之后执行
public void init() 
{
	System.out.println("JSR250-init-method");
}
public  JSR250Way() 
{
	super();
	System.out.println("初始化构造函数-JSR250Way");
}
@PreDestroy    //在Bean销毁之前执行
public void destroy() 
{
	System.out.println("JSR250-destroy-method");
}
}

PrePostConfig.java

@Configuration
@ComponentScan("test")
public class PrePostConfig {
@Bean(initMethod="init",destroyMethod="destroy")
BeanWay beanWay()
{
 return new BeanWay();	
}

@Bean
JSR250Way jsr250Way ()
{
	 return new JSR250Way();
}

}

TestPrePost.java

public class TestPrePost{
public static void main(String[] args){
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PrePostConfig.class);
	BeanWay beanWay = context.getBean(BeanWay.class);
	JSR250Way jsr250Way = context.getBean(JSR250Way.class);
	context.close();
}
}

这里写图片描述

事件

Spring的事件(Application Event)为Bean与Bean之间的消息通信提供了支持。当一个Bean处理完一个任务之后,希望另外一个Bean知道并能做相应的处理,这时我们就需要让另外一个Bean监听当前Bean所发送的事件。
Spring的事件需要遵循如下流程:

  • 自定义事件,继承ApplicationEvent;
  • 定义事件监听器,实现ApplicationListener;
  • 使用容器发布事件;

DemoEvent.java

public class DemoEvent extends ApplicationEvent{
    private String msg;
	public DemoEvent(Object source,String msg) 
	{
		super(source);
		this.msg = msg;
	}
	
	public String getMsg() 
	{
		return msg;
	}
	
	public void setMsg(String msg)
	{
		this.msg = msg;
	}
}

DemoListener.java

@Component
public class DemoListener implements ApplicationListener<DemoEvent>{  //实现ApplicationListener接口,并指定监听的事件类型

	@Override
	public void onApplicationEvent(DemoEvent event) {  //使用onApplicationEvent方法对消息进行处理
		String msg = event.getMsg();
		System.out.println("我(bean-demoListener)接收到了bean-demoPublisher发布的消息:"+msg);	
	}
}

DemoPublisher.java

@Component
public class DemoPublisher {
	@Autowired
	ApplicationContext applicationContext;
	
	public void publish(String msg) {   //使用ApplicationContext  的publish方法来发布。
		applicationContext.publishEvent(new DemoEvent(this, msg));
	}
}

EventConfig.java

@Configuration
@ComponentScan("test")
public class EventConfig {

}

TestApplicationEvent.java

public class TestApplicationEvent{
public static void main(String[] args){
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(EventConfig.class);
	DemoPublisher demoPublisher = context.getBean(DemoPublisher.class);
	demoPublisher.publish("hello application event");
	context.close();
}
}

这里写图片描述

参考书籍:Spring Boot 实战
以上只是学习所做的笔记, 以供日后参考。如有错误请指正,谢谢啦!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值