xml配置bean
Application ac = new ClassPathXmlAppliation(“applicationContext.xml”);
XXX xxx = ac.getBean(XXX.class);
xxx.method;
加载xml -> 解析xml -> 封装BeanDefinition
-> 实例化 -> 初始化 -> 放到容器 -> 从容器中获取
xml四种解析方式:
- DOM解析
- SAX解析
- JDOM解析
- DOM4J解析
容器Map
String Object
Class Object
String ObjectFactory
String BeanDefinition
xml\properties\yaml\json...
无论何种形式只要实现BeanDefinitionReader
规范(接口)进行解析为BeanDefinition
对象
以下仅适用于WebApplicationContext环境
在堆中开辟一块空间,对象的属性值都是默认值
反射
为什么是反射:灵活,可以获取Bean对象中所有方法属性注解以及一系列东西
Class.forName("完全限定名");
对象.getClass();
类名.class;
整个容器的根接口,也是容器的接口,这里也能看到反射相关代码
DefaultListabelBeanFactory
记住以下几个关键的:BeanFactory、 AbstractAutowiredCapableBeanFactory、 DefaultListableBeanFactory
PostProcessor 后置处理器(增强器)
BeanFactoryPostProcessor
:增强BeanDefinition信息BeanPostProcessor
:增强Bean信息实现BeanFactoryPostProcessor,可以自己设置一些属性:如懒加载、单例模式等
实际应用
例:PlaceholderConfigurerSupport
PlaceholderConfigurerSupport类–是BeanFactoryPostProcessor的一个子实现类,spring提供的一个工具类,用于解析bean定义中属性值里面的占位符(
${:}
),此类不能实例化使用<p>Example XML property with default value: <pre class="code"> <property name="url" value="jdbc:${dbname:defaultdb}" /> pre>
给属性设置值,执行init-method(配置中指定的初始化方法)
实例化+初始化->创建对象(init方法在构造方法之后)
调用populate
方法
当Spring容器创建的bean对象在进行具体操作的时候,如果需要容器的其他对象,此时可以将对象实现具体的能拿到该对象Aware接口,来满足当前的需要
例:ApplicationContextAware
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
自定义实现该接口可获取
ApplicationContext
对象
init-method
例:AbstractAutoProxyCreator 与AOP相关(cglib/jdk动态代理)
AbstractAutoProxyCreator类是BeanPostProcessor接口的一个子实现类,意味这重写了postProcessBeforeInitialization前置处理方法和postProcessAfterInitialization后置处理方法
AbstractAutoProxyCreator -> postProcessBeforeInitialization()
/**
* 此处是真正创建aop代理的地方,在实例化之后,初始化之后就行处理
* 首先查看是否在earlyProxyReferences里存在,如果有就说明处理过了,不存在就考虑是否要包装,也就是代理
*
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 获取当前bean的key:如果beanName不为空,则以beanName为key,如果为FactoryBean类型,
// 前面还会添加&符号,如果beanName为空,则以当前bean对应的class为key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 判断当前bean是否正在被代理,如果正在被代理则不进行封装
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 如果它需要被代理,则需要封装指定的bean
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
AbstractAutoProxyCreator -> wrapIfNecessary()
/**
* 先判断是否已经处理过,是否需要跳过,跳过的话直接就放进advisedBeans里,表示不进行代理,如果这个bean处理过了,获取通知拦截器,然后开始进行代理
*
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果已经处理过,直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 这里advisedBeans缓存了已经进行了代理的bean,如果缓存中存在,则可以直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 这里isInfrastructureClass()用于判断当前bean是否为Spring系统自带的bean,自带的bean是
// 不用进行代理的;shouldSkip()则用于判断当前bean是否应该被略过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 对当前bean进行缓存
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 获取当前bean的Advices和Advisors
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 对当前bean的代理状态进行缓存
if (specificInterceptors != DO_NOT_PROXY) {
// 对当前bean的代理状态进行缓存
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 根据获取到的Advices和Advisors为当前bean生成代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 缓存生成的代理bean的类型,并且返回生成的代理bean
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
AbstractAutoProxyCreator -> createProxy()
/**
* 进行代理工厂的创建,然后判断是否需要设置proxyTargetClass,以便于后面决定是不是要进行jdk动态代理还是cglib的动态代理
* 然后把通知器advisors包装下,加入到代理工厂,获取代理对象
*
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 给bean定义设置暴露属性
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
// 获取当前类中相关属性
proxyFactory.copyFrom(this);
// 决定对于给定的bean是否应该使用targetClass而不是他的接口代理,检查proxyTargetClass设置以及preserverTargetClass属性
if (!proxyFactory.isProxyTargetClass()) {
// 判断是 使用jdk动态代理 还是cglib代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 添加代理接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 构建增强器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 设置到要代理的类
proxyFactory.setTargetSource(targetSource);
// 定制代理
customizeProxyFactory(proxyFactory);
// 控制代理工程被配置之后,是否还允许修改通知,默认值是false
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 真正创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
ProxyFactory -> getProxy()
public Object getProxy(@Nullable ClassLoader classLoader) {
// createAopProxy() 用来创建我们的代理工厂
return createAopProxy().getProxy(classLoader);
}
/**
* 创建AOP代理,如果激活了,就需要有激活通知
*
* Subclasses should call this to get a new AOP proxy. They should not
* create an AOP proxy with {@code this} as an argument.
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
// 监听调用AdvisedSupportListener实现类的activated方法
activate();
}
// 通过AopProxyFactory获得AopProxy,这个AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
AopProxy -> getProxy()
3.3后得到完整的Bean对象,从容器中进行获取contxt.getBean()
为什么是上面的创建顺序
参见:BeanFactory
创建过程
* <p>Bean factory implementations should support the standard bean lifecycle interfaces * as far as possible. The full set of initialization methods and their standard order is: * <ol> * <li>BeanNameAware's {@code setBeanName} * <li>BeanClassLoaderAware's {@code setBeanClassLoader} * <li>BeanFactoryAware's {@code setBeanFactory} * <li>EnvironmentAware's {@code setEnvironment} * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver} * <li>ResourceLoaderAware's {@code setResourceLoader} * (only applicable when running in an application context) * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher} * (only applicable when running in an application context) * <li>MessageSourceAware's {@code setMessageSource} * (only applicable when running in an application context) * <li>ApplicationContextAware's {@code setApplicationContext} * (only applicable when running in an application context) * <li>ServletContextAware's {@code setServletContext} * (only applicable when running in a web application context) * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors * <li>InitializingBean's {@code afterPropertiesSet} * <li>a custom init-method definition * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors * ol>
销毁过程
* <p>On shutdown of a bean factory, the following lifecycle methods apply: * <ol> * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors * <li>DisposableBean's {@code destroy} * <li>a custom destroy-method definition * ol>
在不同的阶段处理不同的工作,如何处理?
观察者模式:监听器+监听事件+多播器(广播器)
BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
FactoryBean
当调用getBean(“
XXXbeanName
”)时,Spring通过反射机制发现XXXFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法XXXFactoryBean#getObject()方法返回。如果希望获取XXXFactoryBean的实例,则需要在使用getBean(“XXXbeanName
”)方法时在beanName前显示的加上"&“前缀:如getBean(”&XXXbeanName
");详情参见