通过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();
}
}
}