程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 利用Java注解特性加載屬性文件(properties)的值到Java類

利用Java注解特性加載屬性文件(properties)的值到Java類

編輯:關於JAVA

在此之前我都是寫個PropertyUtil類來加載配置文件,然後通過get方法,把key對應的值取出來.

Spring提供一個PropertyPlaceholderConfigurer類,可以讀取配置文件,然後在Spring配置文件通過${hibernate.dialect}這種方式注入到JavaBean中,有個不好的地方就是,要在代碼中取的時候不是很方便.

然後在接觸到Java注解特注解技術以後,感覺這個東東很好,hibernate映射,WebService都可以通過注解來完成,方便的很多,然後就在想能不能通過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方法執行之前先賦值好.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved