spring在java基础上封装了资源访问,简单易用。
Resource接口 根据资源路径的不同提供了不同的实现类:
ByteArrayResource :通过二进制数组构造
ClassPathResource:类路径下的资源访问
FileSystemResource:文件系统资源访问
InputStreamResource:对应InputStream资源
ServletContextResource:web容器上下文资源
UrlResource:http,ftp资源....
EncodedResource 可以对资源进行编码 满足不同的资源类型读取操作
spring实现时候
new InputStreamReader(this.resource.getInputStream(), this.encoding);创建输入流的时候就会指定它的编码格式。
例子:
首先在classpath下放load.properties gbk编码
//FileSystemResource:文件系统资源访问
Resource fileSystem = new FileSystemResource("F:\\salmon\\WebRoot\\WEB-INF\\classes\\load.properties");
System.out.println(fileSystem.getFilename());
//ClassPathResource:类路径下的资源访问
Resource classPath = new ClassPathResource("load.properties");
System.out.println(classPath.getFilename());
Properties p = new Properties();
EncodedResource encRes = new EncodedResource(classPath,"gbk");
p.load(encRes.getReader());
System.out.println(p.get("salmon"));
以上都是通过指定具体的实现类来达到加载不同的资源目的
但是spring实现了一套资源加载接口能够通过在路径前加上区分 后统一读取资源。
注意:
classpath:classpath*: ClassPathResource
file: FileSystemResource
http:// UrlResource
ftp: UrlResource
classpath:classpath*:区别:像maven这样的分模块打包时候 如果出现在不同包里面出现同样前缀的资源文件 classpath:spring-*.xml classpath*:spring-*.xml
如果是classpath只会加载工程下面的 而 classpath*:spring-*.xml 会加载所有的包下面的。
PathMatchingResourcePatternResolver扫描不到eclipse导出来的jar包里面的配置文件
原因:导出时候没有加上导出时记得钩选"Add directory entries"
用jar命令,比较了一下两种方法打出的jar包的区别,如图:
例如:PathMatchingResourcePatternResolver支持ant类型风格匹配。
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:load.properties");
encRes = new EncodedResource(res,"gbk");
p.load(encRes.getReader());
System.out.println(p.get("salmon"));
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
BeanFactory会懒加载bean
ApplicationContext(继承BeanFactory 子类ClassPathXmlApplicationContext,FileSystemXmlApplicationContext,AnnotationConfigApplicationContext ) 初始化时候就加载
所有单例bean缓存 protype 直接返回不再管理
ApplicationContext生命周期图:
spring 通过配置文件描述bean和bean之间的依赖关系,利用java语言的反射功能实例化bean并建立bean之间的依赖关系。spring的ioc容器在完成这些底层工作的基础上还提供了bean的缓存,代理,事件发布 资源装载等高级服务。
循环依赖问题:
通过构造函数方式 有可能发送循环依赖,在构造对象时候互相依赖对方 造成死锁。
解决方法通过set方式注入,set互相持有引用 对象都能顺利构造出来就存在引用。 所以不存在循环依赖问题。
使用p命名空间:
加入 xmlns:p="http://www.springframework.org/schema/p" //因为b-ref a-ref这些为可变的 所以指定xsi:schemaLocation就没有意义了。
<bean id="a" class="com.tt.test.TestA" p:b-ref="b"/>
<bean id="b" class="com.tt.test.TestB" p:a-ref="a"/>
为单例注入多例的对象,因为单例只有一份 缓存在spring维护的Map中所以你没有办法没有获取到新的多例的属性,怎么办?
1.在调用多例的getXXX方法时候,重新从容器中进行获取。bean实现BeanFactoryAware接口 这样就能获取到容器对象了。
2.<bean id="me" class="XXXXXXXXXXXXXXX">
<lookup-method name="getYou" bean="you"/>
</bean>
这样配置的bean,getYou方法会被spring进行动态代理 代理后内部实现就像上面的一样。
两个没有关系的bean让他们先后实例化
<bean id="me" class="XXXXXXXXXXXXXXX" depends-on="you">
这样you这个bean一定强制先实例化后实例化me
几个后处理bean实现:
属性编辑器:CustomEditorConfigurer 属性customEditors 维护一个map key为类名 值 自定义属性编辑器
自定义属性编辑器: 继承PropertyEditorSupport重新setAsText 最好setValues进行设置。
属性占位符:PropertyPlaceholderConfigurer
<context:property-placeholder location="classpath:*****"/>
注解:
@Component
@Respository dao层
@Service service层
@Controller controller层
@Autowised 根据类型注入 如果加载set方法上面 那么参数会根据类型进行注入
@Qualifer("XXXX") Autowised 注入时候如果有多个对象 可以再加上@Qualifer("XXXX")这个注解确定是哪个 同理用在方法上面
这些都是一类注解 能被context:component-scan 扫描 只是赋予了不同的意义有不同的处理比如异常
<context:component-scan base-package="com.test"></context:component-scan>
表示扫描com.test下面的所有类
<context:component-scan base-package="com.test">
<context:include-filter type="" expression=""/>
<context:exclude-filter type="" expression=""/>
</context:component-scan>
这里的type可以选择注解 或者正则之类的 配置很灵活 121
spring国际化原理:
locale的构造 语言/地址
Locale local1 = new Locale("zh","CN");//大陆
Locale local2 = new Locale("zh","HK");//香港
Locale local3 = new Locale("zh","TW");//台湾
MessageSource里面有
String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException类是的方法
定义了获取资源信息的方式 传递资源文本中定义的key 需要格式化的参数 已经本地化信息获取对应的本地化字符串
ApplicationContext实现了MessageSource 所以只要你持有容器的引用就能获取资源文本信息。
你只要配置一个名称为messageSource 的bean对象就行了
<bean id="messageSource " class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>com/test/i18n/fmt_resource</value>//fmt_resource_en_US.properties fmt_resource_zh_CN.properties .......
</list>
</property>
<property name="cacheSends" values="5"/>//秒
</bean>
通过容器引用调用的时候:
容器间接调用 return ctx.getBean("messageSource ").getMessage("XXXX".params,locale);