spring 不知道的知识点
<aop:scoped-proxy/>
-
例子:
<!-- 例子1: --> <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> <bean id="userManager" class="com.foo.UserManager"> <property name="userPreferences" ref="userPreferences"/> </bean> <!-- 例子2: --> <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> <aop:scoped-proxy/> </bean> <bean id="userManager" class="com.foo.UserManager"> <property name="userPreferences" ref="userPreferences"/> </bean> -
说明:第二个例子中,userManager注入的是userPreferences的代理对象,当调用这个代理对象的方法时,会自动从httpsession中获取对应的userPreferences对象并调用其方法,从而实现在长生命周期对象里注入短生命周期的对象。创建代理用的,修改BeanDefinition,变成代理对象,其他bean引用时获取的也就是代理对象了
-
class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator { private static final String PROXY_TARGET_CLASS = "proxy-target-class"; public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { boolean proxyTargetClass = true; if (node instanceof Element) { Element ele = (Element) node; if (ele.hasAttribute("proxy-target-class")) { proxyTargetClass = Boolean.valueOf( ele.getAttribute("proxy-target-class")).booleanValue(); } } BeanDefinitionHolder holder = ScopedProxyUtils.createScopedProxy( definition, parserContext.getRegistry(), proxyTargetClass); String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition .getBeanName()); parserContext.getReaderContext().fireComponentRegistered( new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName)); return holder; } }
spring 中
Aware接口系列作用接口名 接口作用 ApplicationContextAware 获取到 ApplicationContext接口实例,然后通过这个上下文类就可以做一些其他的事,比如获取 bean(,spring文档中并不推荐用这个类获取bean,理由是这样会增加耦合性原文One use would be the programmatic retrieval of other beans. Sometimes this capability is useful. However, in general, you should avoid it, because it couples the code to Spring and does not follow the Inversion of Control style, where collaborators are provided to beans as properties.)、访问文件资源、发布应用事件(这个功能是因为ApplicationContext接口继承了ApplicationEventPublisherAware)、访问MessageSource等。ApplicationEventPublisherAware 通过此接口获取到 ApplicationEventPublisher接口实例,然后就可以发布事件了,这个功能需要配合ApplicationEvent接口使用,可以用来实现异步发送短信、邮件之类的功能,这样也有助于解耦。BeanClassLoaderAware 获取当前 bean 的类加载器 BeanFactoryAware 获取 BeanFactory类实例,BeanFactory是访问 spring bean 容器根接口BeanNameAware 获取 bean 名字的接口 LoadTimeWeaverAware 获取 LoadTimeWeaver接口实例。LoadTimeWeaver用于在类加载时实现织入(比如AspectJ类加载时织入,AspectJ还可以编译器织入)MessageSourceAware 获取 MessageSource接口实例,MessageSourceAware`用于实现国际化NotificationPublisherAware 获取 NotificationPublisher接口实例,spring 对 jmx的支持ResourceLoaderAware 获取 ResourceLoader接口实例,这个类在 spring 中用来加载资源ServletConfigAware 获取 ServletConfig接口实例ServletContextAware 获取 ServletContext接口实例BeanPostProcessor- 先创建
BeanPostProcessor对象,然后再创建 bean 对象,然后再调用BeanPostProcessor中的前后处理方法 BeanPostProcessor被实例化顺序- 1、首先是 spring 默认的四个
BeanPostProcessororg.springframework.context.support.ApplicationContextAwareProcessor,这个类默认修饰符,外部不可见org.springframework.context.support.ApplicationListenerDetector,这个类默认修饰符,外部不可见org.springframework.web.context.support.ServletContextAwareProcessororg.springframework.context.annotation.ConfigurationClassPostProcessor
- 2、然后是实现了
PriorityOrdered接口的BeanPostProcessor - 3、然后是实现了
Ordered接口的BeanPostProcessor - 4、最后是没有实现上述两个接口的
BeanPostProcessor
- 1、首先是 spring 默认的四个
- 可能遇到的问题:
Bean someBean is not eligible for getting processed by all BeanPostProcessor interfaces (for example: not eligible for auto-proxying)- 原因:
BeanPostProcessor实例化顺序靠前的BeanPostProcessor依赖了实例化顺序中比较靠后的BeanPostProcessor处理的bean,导致bean 被未经过处理就提前注入了(也就是说 bean 被提前加载了),从而使 bean 未达到预期效果,这时 spring 的org.springframework.context.support.PostProcessorRegistrationDelegate.BeanPostProcessorChecker类会打印Bean someBean is not eligible for getting processed by all BeanPostProcessor interfaces (for example: not eligible for auto-proxying)这样的提示信息 - 参考:
- 原因:
-