Spring 学习笔记 —— bean

通过xml创建bean 

<?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:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
		
  
	
	<!-- <bean id="hello" class="cn.fg.spring.demo.Hello" init-method="init" destroy-method="destroy">
		<property name="name" value="zhangsan"></property>
	</bean>
	
	<bean class="cn.fg.spring.demo.HelloPostProcessor" /> -->
	
	<bean id="person" class="cn.fg.test.Person"></bean>
	<bean id="student" class="cn.fg.test.Student"></bean>
	<bean id="teacher" class="cn.fg.test.Teacher"></bean>
	
	<bean id="hello" class="cn.fg.test.Hello">
		<!-- 构造方法赋值 -->
		<constructor-arg name="name" value="李四"></constructor-arg>
		<constructor-arg name="age" value="18"></constructor-arg>
		
		<!-- 属性赋值 -->
		<property name="name" value="张三"></property>        <!-- 基本数据类型赋值 -->
		<property name="person" ref="person"></property>     <!-- 对象赋值 -->
		<property name="person.name" value="李四"></property> <!-- 级联赋值 -->
		<property name="teacher">  
			<bean class="cn.fg.test.Teacher"></bean> <!-- 对象赋值,内部bean 等同于new Student() -->
		</property>
		<property name="roles">    <!-- 集合赋值(基本数据类型) -->                          
			<list>
				<value>普通用户</value>
				<value>管理员</value>
			</list>
			<!-- <array></array> -->  <!-- 数组 -->
			<!-- <set></set> -->      <!-- set集合 -->
		</property>
		<property name="students">  <!-- 集合赋值(对象) -->                       
			<list>
				<ref bean="student" />
				<bean class="cn.fg.test.Student"></bean> 
			</list>
		</property>
		<property name="map">    <!-- map赋值 -->                          
			<map>
				<entry key="k1" value="v1"></entry>
				<entry key="k2" value-ref="person"></entry>
			</map>
		</property>
		<property name="properties">   <!-- Properties类赋值 -->                    
			<props>
				<prop key="username">root</prop>
				<prop key="password">root</prop>
			</props>
		</property>
	</bean>
	
	<!-- util的使用 -->
	<util:list id="students">
		<list>
			<ref bean="student"/>
		</list>
	</util:list>

    <util:properties id="myProperties" location="classpath:my.properties">

	@autowired
	Properties myProperties

	<!-- util更多使用搜百度 -->    
	
	<bean id="hello2" class="cn.fg.test.Hello">
		<property name="students" ref="students"></property>
	</bean>
	

	<!-- 父bean,使用abstract="true",该bean不会被ioc容器实例化,仅做模板使用 -->
	<bean id="person_base" abstract="true">
		<property name="name" value="人类"></property>
	</bean>
	<bean id="person" class="cn.fg.test.Person" parent="person_base"></bean> 
	
	<bean id="person_base" class="cn.fg.test.Person"></bean>
	<bean id="person" parent="person_base"> <!-- 继承父bean -->
		<property name="name" value="子类"></property> <!-- 重新复制 -->
	</bean> 
	
	<!-- depends-on:依赖bean,若没有设置依赖bean,则hello bean会报错 -->
	<bean id="hello" class="cn.fg.test.Hello" depends-on="person"></bean>
	
	
</beans>
<!-- 通过工厂方法的方式来配置 bean -->
	<!-- 1. 通过静态工厂方法: 一个类中有一个静态方法, 可以返回一个类的实例(了解) -->
	<!-- 在 class 中指定静态工厂方法的全类名, 在 factory-method 中指定静态工厂方法的方法名 -->
	<bean id="dateFormat" class="java.text.DateFormat" factory-method="getDateInstance">
		<!-- 可以通过 constructor-arg 子节点为静态工厂方法指定参数 -->
		<constructor-arg value="2"></constructor-arg>
	</bean>
	
	<!-- 2. 实例工厂方法: 先需要创建工厂对象, 再调用工厂的非静态方法返回实例(了解) -->
	<!-- ①. 创建工厂对应的 bean -->
	<bean id="simpleDateFormat" class="java.text.SimpleDateFormat">
		<constructor-arg value="yyyy-MM-dd hh:mm:ss"></constructor-arg>
	</bean>
	
	<!-- ②. 有实例工厂方法来创建 bean 实例 -->
	<!-- factory-bean 指向工厂 bean, factory-method 指定工厂方法(了解) -->
	<bean id="datetime" factory-bean="simpleDateFormat" factory-method="parse">
		<!-- 通过 constructor-arg 执行调用工厂方法需要传入的参数 -->
		<constructor-arg value="1990-12-12 12:12:12"></constructor-arg>
	</bean>
//配置通过 FactroyBean 的方式来创建 bean 的实例
//<bean id="user" class="cn.fg.UserBean"></bean>

public class UserBean implements FactoryBean<User>{

	/**
	 * 返回的 bean 的实例
	 */
	@Override
	public User getObject() throws Exception {
		User user = new User();
		user.setUserName("abc");
		user.setWifeName("ABC");
		
		List<Car> cars = new ArrayList<>();
		cars.add(new Car("ShangHai", "BuiKe", 180, 300000));
		cars.add(new Car("ShangHai", "CRUZE", 130, 150000));
		
		user.setCars(cars);
		return user;
	}

	/**
	 * 返回的 bean 的类型
	 */
	@Override
	public Class<?> getObjectType() {
		return User.class;
	}

	/**
	 * 返回的 bean 是否为单例的
	 */
	@Override
	public boolean isSingleton() {
		return true;
	}

}

通过注解创建bean

<?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:util="http://www.springframework.org/schema/util"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
		
  
	<!-- 
		配置自动扫描组件,base-package:基包,该包及子包下的类只要有@Component注解的,都会由ioc容器创建bean进行管理 
		@Service、@Controller......这些注解本身又引用了@Component,也能被自动扫描为bean
		resource-pattern:只扫描基包下的哪些资源
	-->
	<context:component-scan base-package="cn.fg.test" resource-pattern="service/*.class">
		<!-- 排除@Controller注解,该注解的类不会被扫描为bean-->
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
		<!-- 可以写多个 -->
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
		
		<!-- 
			type="assignable" 按类排除 
			type="annotation" 按注解排除
			type="aspectj" aspectj表达式
			type="regex" 正则表达式
			type="custom" 自定义
		-->
		<context:exclude-filter type="custom" expression="cn.fg.test.UserService"/>
		
	</context:component-scan>
	
	<context:component-scan base-package="cn.fg.test" use-default-filters="false">
		<!-- 只扫描@Component注解,use-default-filters必须设置为false,否则还是会扫描其他注解的 -->
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
	</context:component-scan>
	
</beans>
@Component("user") //可以指定bean id为user,不指定则为userService
public class UserService  {

}

bean的生命周期

public class Hello {
	
	public Hello(){
		System.out.println("1.Hello.......................");
	}

	private String name;
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		System.out.println("2.setName....................");
		this.name = name;
	}
	
	public void init(){
		System.out.println("4.init......................");
	}
	
	public void destroy(){
		System.out.println("6.destroy...................");
	}
}
//Bean后置处理器,允许在调用初始化方法前后对Bean进行额外的处理.
//BeanPostProcessor 很重要,它下面有很多实现类,比如ApplicationContextAwareProcessor,只要实现了ApplicationContextAware接口,ApplicationContextAwareProcessor后置处理器就会把ioc容器注入到bean中
public class HelloPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("3.postProcessBeforeInitialization:"+bean+":"+beanName);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		//beanName为bean标签的id值,若未设置id则为全类名
		System.out.println("5.postProcessAfterInitialization:"+bean+":"+beanName);
		/*if(bean instanceof Hello){ //可以修改bean
			Hello hello = (Hello) bean;
			hello.setName("李四");
			return hello;
		}*/
		return bean;
	}

}
	<bean id="hello" class="cn.fg.spring.demo.Hello" init-method="init" destroy-method="destroy">
		<property name="name" value="zhangsan"></property>
	</bean>
	
	<bean class="cn.fg.spring.demo.HelloPostProcessor" />
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-demo.xml");
		//多实例bean是获取对象时才创建对象,单实例bean时ioc容器加载过程中就会实例化
		applicationContext.close(); //关闭容器时,如果是多实例bean是不会执行销毁方法的
	}
#输出结果
1.Hello.......................
2.setName....................
3.postProcessBeforeInitialization:cn.fg.spring.demo.Hello@3d93f119:hello
4.init......................
5.postProcessAfterInitialization:cn.fg.spring.demo.Hello@3d93f119:hello
6.destroy...................
//还可以通过实现接口,实现初始化和销毁
public class Hello implements InitializingBean, DisposableBean {
	
	@Override
	public void destroy() throws Exception {
		//等同于destroy方法
		System.out.println("destroy.............");

	}

	@Override
	public void afterPropertiesSet() throws Exception {
		//等同于init方法
		System.out.println("afterPropertiesSet............");
	}

}
@Component
public class Hello {
	
	@PostConstruct
	public void init() {
		//通过注解调用初始化方法
	}
	
	@PreDestroy
	public void destroy() {
		//通过注解调用销毁方法
	}
}

//这两个注解的原理也是通过InitDestroyAnnotationBeanPostProcessor后置处理器处理的

BeanFactoryPostProcessor

BeanFactory:即ioc容器,就是用来创建bean的。BeanFactoryPostProcessor:ioc容器后置处理器,在ioc容器标准初始化之后调用,用来定制和修改BeanFactory的内容;所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory...");
		int count = beanFactory.getBeanDefinitionCount();
		String[] names = beanFactory.getBeanDefinitionNames();
		System.out.println("当前BeanFactory中有"+count+"个Bean");
		System.out.println(Arrays.asList(names));
	}

}
MyBeanFactoryPostProcessor...postProcessBeanFactory...
当前BeanFactory中有10个Bean
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, mainConfig, myBeanFactoryPostProcessor, propertiesUtil, hello]

#上面是BeanFactoryPostProcessor后置处理器在bean实例化之前输出的结果

Hello...构造方法......

BeanDefinitionRegistryPostProcessor

interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor;在所有bean定义信息将要被加载,bean实例还未创建的;优先于BeanFactoryPostProcessor执行;利用BeanDefinitionRegistryPostProcessor给容器中再额外添加一些组件;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor{

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount());
	}

	//BeanDefinitionRegistry Bean定义信息的保存中心,以后BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例;
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount());
		//RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
		registry.registerBeanDefinition("person", beanDefinition);
	}

}
postProcessBeanDefinitionRegistry...bean的数量:11
MyBeanDefinitionRegistryPostProcessor...bean的数量:12

ApplicationListener

监听容器中发布的事件

@Component
//自定义ApplicationListener
//ApplicationListener<E extends ApplicationEvent>  ApplicationEvent下面有多个子事件,例如ContextRefreshedEvent容器刷新完成事件
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {

	//当某个地方使用AbstractApplicationContext.publishEvent(ApplicationEvent)发布事件的使用就会回调此方法
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		System.out.println("收到事件:"+event);
	}

}
//拿到applicationContext,自己发布一个事件
applicationContext.publishEvent(
			new ApplicationEvent(new String("我发布的事件")) {
			}
		);

//调用该方法后,spring会发布ContextClosedEvent事件
applicationContext.close(); 
#这是spring容器发布的事件,ContextRefreshedEvent
收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@66d33a: startup date [Tue Jun 23 22:51:21 CST 2020]; root of context hierarchy]

#这是我自己发布的事件
收到事件:cn.fg.demo.config.MainConfig$1[source=我发布的时间]

#这是spring容器发布的事件,ContextClosedEvent
收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@66d33a: startup date [Tue Jun 23 22:51:21 CST 2020]; root of context hierarchy]

还可以使用注解监听事件

@Service
public class UserService {
	
	@EventListener(classes={ApplicationEvent.class})
	public void listen(ApplicationEvent event){
		System.out.println("UserService。。监听到的事件:"+event);
	}

}


//可以自己创建一个事件,只监听自己的事件
@EventListener(UserEvent.class )
public void listen(UserEvent event){
	System.out.println("监听到了用户事件" + event);
}	

public class UserEvent extends ApplicationEvent {
	
	private static final long serialVersionUID = -7146064019198614307L;

	public UserEvent(Person person) {
		super(person);
	}

}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

//ioc容器刷新方法
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 在这里面依次执行 
				// BeanDefinitionRegistryPostProcessor接口的方法,先postProcessBeanDefinitionRegistry(),后postProcessBeanFactory()
				// BeanFactoryPostProcessor接口的方法
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 向beanFactory注册BeanPostProcessors,保存信息,不是执行BeanPostProcessors
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 国际化,初始化后可以注入MessageSource
				initMessageSource();

				// Initialize event multicaster for this context.
				// 初始化多播器,publishEvent之前必须要先有多播器,否则无法回调publishEvent里面的方法
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 子类(子容器)重写这个方法添加其他组件
				onRefresh();

				// Check for listener beans and register them.
				// 把监听器注册到多播器中
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 初始化剩下的非懒加载的单实例bean.
				// 这里面有BeanPostProcessor后置处理器的执行逻辑
				// 这里面有@EventListener的处理逻辑
				// bean的创建也是在这里完成的
				finishBeanFactoryInitialization(beanFactory);

				//@EventListener注解创建的监听回调时机,在BeanPostProcessor之后处理的,因此不能BeanPostProcessor中发布事件,通过接口实现的监听时在registerListeners中处理的,所以可以在BeanPostProcessor发布事件

				// Last step: publish corresponding event.
				// 在这里面会发布相应事件,如ContextRefreshedEvent
				finishRefresh();

			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值