`
soongbo
  • 浏览: 87159 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

利用Java注解特性加载属性文件(properties)的值到Java类

阅读更多

在Spring中JavaBean的初始化顺序就是为现在写这个做准备的,要实现现在说的这个功能,大体方案有如下:

  1.定义一个注解类

  2.在需要加载属性的JavaBean的属性set方法上写注解,注解的参数就是key

  3.在Spring启动的时候,去读取属性文件,然后把值赋给JavaBean

  我们在上一篇写在Spring中JavaBean的初始化顺序提到了,如果一个JavaBean实现了BeanPostProcessor接口,那么其他Bean初始化以后都会交给这个Bean来处理.这样我们就可以写一个JavaBean实现BeanPostProcessor接口,这个Bean有个属性,它指向属性文件路径,在这个Bean初始化的时候读取属性文件内容,然后在postProcessBeforeInitialization方法里面对写了注解的Bean进行赋值.这样一个实现思路似乎很顺其自然,都是自己觉得不是很好,Spring通过PropertyPlaceholderConfigurer这样类来加载属性文件,而我们有写了另外一个类,这样一是不够统一,二是不够可能会造成多个属性文件.解决办法就是扩展PropertyPlaceholderConfigurer类.写一个类继承PropertyPlaceholderConfigurer类.然后在PropertyPlaceholderConfigurer初始化完成以后,获取加载的属性文件内容,在postProcessBeforeInitialization里面把写过注解的类属性进行赋值.那么怎么确定什么时候PropertyPlaceholderConfigurer加载完成呢,根据Spring中JavaBean的初始化顺序,我们知道一个JavaBean如果实现了InitializingBean接口,那么Spring容器会在这个Bean初始化以后调用afterPropertiesSet方法,现在我写个类继承PropertyPlaceholderConfigurer类,实现BeanPostProcessor, InitializingBean 这个两个接口那么刚刚提到的问题就可以解决了,下面是实现代码

package com.test.annotation;
import java.lang.reflect.Method;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.ReflectionUtils;
public class AnnotationBeanPostProcessor extends PropertyPlaceholderConfigurer implements BeanPostProcessor, InitializingBean {
   private java.util.Properties pros;  
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName)
      throws BeansException {
    // TODO Auto-generated method stub
    return bean;
  }
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
    if(bean.getClass().getAnnotation(Property.class)!=null){
      Method[] methods = bean.getClass().getDeclaredMethods(); 
      for (Method method : methods) {  
        Property p = method.getAnnotation(Property.class);
        if(p!=null){
//         这里进行参数类型转换
          Object para=pros.getProperty(p.name());
          if((method.getParameterTypes()[0]).getName().equals("java.lang.Integer")){
            para= new Integer(para.toString());
          }
          ReflectionUtils.invokeMethod(method, bean, new Object[]{para});
        }
      }  
    }
    return bean;
  }
  @Override
  public void afterPropertiesSet() throws Exception {
    pros = mergeProperties();  
  }
}
package com.test.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Property {
  String name() default "";
}
package com.test;
import com.test.annotation.Property;
@Property
public class Bean {
  private String name;
  private Integer age;
private String address;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getAddress() {
    return address;
  }
  @Property(name="com.test.Bean.address")
  public void setAddress(String address) {
    this.address = address;
  }
  public Integer getAge() {
    return age;
  }
  @Property(name="com.test.Bean.age")
  public void setAge(Integer age) {
    this.age = age;
  }
}
package com.test;
import com.test.annotation.Property;
@Property
public class JavaBean {
  private String name;
  private String address;
  public String getName() {
    return name;
  }
  @Property(name="com.test.JavaBean.name")
  public void setName(String name) {
    this.name = name;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
}
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
  /**
   * @param args
   */
  public static void main(String[] args) {
     ApplicationContext context = 
        new ClassPathXmlApplicationContext("spring.xml"); 
     System.out.println("加载配置文件结束");
     System.out.println("--------------------------------------------");
     JavaBean javaBean=(JavaBean)context.getBean("javaBean");
     System.out.println(javaBean.getName());
     System.out.println(javaBean.getAddress());
     System.out.println("--------------------------------------------");
     Bean bean=(Bean)context.getBean("bean");
     System.out.println(bean.getName());
     System.out.println(bean.getAddress());
     System.out.println(bean.getAge());
     System.out.println("--------------------------------------------");
  }
}
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  <bean id=
attribute-value>"propertyConfigurer" class="com.test.annotation.AnnotationBeanPostProcessor">
    <property name="locations">
      <list>
        <value>classpath*:system.properties</value>
      </list>
    </property>
  </bean>
  <bean id="javaBean" class="com.test.JavaBean">
    <property name="address" value="${com.test.JavaBean.address}"></property>
  </bean>
  <bean id="bean" class="com.test.Bean">
    <property name="name" value="${com.test.Bean.name}"></property>
  </bean>
</beans>

 

  ps:之所以要继承PropertyPlaceholderConfigurer类,还有一个原因就是,原来通过${}注入值的方式还可以用

  BeanPostProcessor有两个方法,为什么要写在postProcessBeforeInitialization里面,而不是postProcessAfterInitialization里面,原因在于postProcessBeforeInitialization方法是在Bean的init方法之前执行,在init方法里面可能会用到类的属性,所以必须在init方法执行之前先赋值好.

 

<!-- 分页 -->
分享到:
评论

相关推荐

    Java高级程序设计实战教程第三章-Java反射机制.pptx

    3.1 应用场景 在一些开源框架里,如Spring,Struts,Hibernate,MyBatis等,应用程序会提供一个配置文件如xml文件或者properties,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射机制...

    JAVA Spring框架实现登陆查询 完整搭建框架方法的word文档 包含mysql文件

    4 配置加载sping-mybaties文件所需要的类 5 配置处理javabean类销毁的类 6 配置sping-mvc的前端控制器 7 配置 项目默认访问页面和设置session的会话时间(可选,不是必须的) Ssm项目搭建完了!现在...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    inject.property

    jar 并运行集成测试mvn 全新安装如何使用注解构建 jar 并将其与依赖项一起删除使用@PropertiesFiles 注解注解将执行注入的类,该注解将列出将要加载的所有属性文件 @PropertiesFiles({"file1.properties", "file2....

    day020-继承加强和设计模式代码和笔记.rar

    由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用, 所以 不允许直接通过引用进行操作。 2. 拓展类加载器(Extension classLoader): 扩展类加载器是...

    jTester使用指南(带书签).pdf

    配置jtester.properties文件 DataMap语法详解 对指定表进行数据插入操作 用DataMap插入多条数据 DataMap的数据提供器功能 准备数据的一些补充 对指定表进行数据验证操作 其他数据库操作 多数据库测试 使用eclipse...

    社区协作配置标准Tamaya.zip

    属性通常会以key = value的形式进行指定,这些属性会以文件的形式来提供并且会加载到一个Java Properties对象中。令人遗憾的是,OSGi、Spring、Java EE、SE以及其他在Java中运行的框架和解决方案都提供了自己的配置...

    Java学习笔记-个人整理的

    {2.10.1}类的属性}{60}{subsection.2.10.1} {2.10.2}类的方法}{61}{subsection.2.10.2} {2.10.3}静态代码块}{62}{subsection.2.10.3} {2.11}\ttfamily final}{63}{section.2.11} {2.12}\ttfamily abstract}{63}...

    springboot参考指南

    Application属性文件 iv. 23.4. 特定的Profile属性 v. 23.5. 属性占位符 vi. 23.6. 使用YAML代替Properties i. 23.6.1. 加载YAML ii. 23.6.2. 在Spring环境中使用YAML暴露属性 iii. 23.6.3. Multi-profile YAML文档...

    SpringBoot:springboot基础服务

    2.2其他的属性文件需要使用@PropertySource(“ classpath:/config/cs.properties”)来指定文件的位置(只要存在该注解即可),然后再使用@Value注入; 2.3将属性文件装配成一个bean,@ ConfigurationProperties...

    openConf:本地配置注解获取

    conf 本地配置注解获取 说明 version 1.3 ...新增了自定义配置文件,使用注解ConfSource(""),指定配置文件路径,默认为classpath:configer.properties version 1.0 本项目主要用于帮助开发者可以更快更方便

    Spring中文帮助文档

    5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的PropertyEditor实现 6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 ...

    Spring API

    5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的PropertyEditor实现 6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 ...

    springboot知识点整理

    2.4 properties配置文件乱码问题 24 2.5 @ConfigurationProperties与@Value的区别 25 2.6 配置@PropertySource、@ImportResource、@Bean 27 2.7 配置文件占位符 30 2.8 Profile多环境支持 31 2.9 配置文件的加载位置...

    Java SpringBoot课件+源码视频教程

    11、_SpringBoot_配置-yaml配置文件值获取 , y( ] x3 r% o7 ]5 i 12、_SpringBoot_配置-properties配置文件编码问题 13、_SpringBoot_配置-@ConfigurationProperties与@Value区别 14、_SpringBoot_配置-@Property...

    基于SpringMVC+Spring+MyBatis开发的个人博客网站-毕业设计.zip

    实体类中多次使用到 @Data 注解,请确保你的 IDE 安装了 Lombok 插件,否则找不到 getter/setter 方法 数据库乱码,在MySQL安装路径,比如(E:\MySQL\MySQL Server 5.5)下找到my.ini文件进入编辑,修改这两处地方...

    128元尚硅谷Java视频教程_SpringBoot视频教程(上)核心技术篇

    12、尚硅谷_SpringBoot_配置-properties配置文件编码问题 13、尚硅谷_SpringBoot_配置-@ConfigurationProperties与@Value区别 14、尚硅谷_SpringBoot_配置-@PropertySource、@ImportResource、@Bean 15、尚硅谷_...

    HibernateAPI中文版.chm

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    hibernate3.2中文文档(chm格式)

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    hibernate3.04中文文档.chm

    符合Java习惯的关系数据库持久化 目录 前言 1. 翻译说明 2. 版权声明 1. 在Tomcat中快速上手 1.1. 开始Hibernate之旅 1.2. 第一个持久化类 1.3. 映射cat 1.4. 与Cat同乐 1.5. 结语 2. Hibernate入门 ...

Global site tag (gtag.js) - Google Analytics