乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      把properties直接注入到object中去(spring-plugin)

       CevenCheng 2012-06-10
      1背景 
      Spring2.5支持使用annotation來配置我們的service,比如如下代碼:
      Java代碼 復(fù)制代碼
      1. @Service("userService")
      2. public class UserServiceImpl extends BaseServiceSupport implements UserService {
      3. public void xxx() {
      4. }
      5. }
      @Service("userService")
      public class UserServiceImpl extends BaseServiceSupport implements UserService {
      
      	public void xxx() {
      
      	}
      }


      這樣就表示這個(gè)service需要被spring管理,不過只是這樣做是不夠的,我們還需要在applicationcontext***.xml中加入這么一段: 
      Java代碼 復(fù)制代碼
      1. <context:component-scan base-package="xxxxxxx"/>
      <context:component-scan base-package="xxxxxxx"/>

      這么一來這個(gè)xxxxxxx包下所有的使用@Service這個(gè)注釋的對象都會自動(dòng)的被spring管理。 

      雖然這樣看上去很美好,但是卻是不滿足我們的需求的,因?yàn)槲覀兊膕ervice中,或者其他被管理的bean中有時(shí)候需要一些配置,比如說String,Integer等等,而且這些配置的值一般都來自Properties文件,一般情況下我們會使用如下這段代碼: 
      Java代碼 復(fù)制代碼
      1. <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      2. <property name="locations">
      3. <list>
      4. <value>classpath:jdbc.properties</value>
      5. </list>
      6. </property>
      7. </bean>
      <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      		<property name="locations">
      			<list>
      				<value>classpath:jdbc.properties</value>
      			</list>
      		</property>
      	</bean>	

      這樣我們就可以通過${}來引用到properties文件中的值。 

      不過使用了@service之后,我們就無法通過${}來得到properties中的值了。downpour是spring2.5使用的先行者,他很早就意識到這個(gè)問題,通過我們的討論,確定了解決問題的方向。下面我把這個(gè)方案拿出來和大家共享。 

      2目標(biāo): 
      我們的目標(biāo)是實(shí)現(xiàn)一個(gè)Annotation,代碼如下: 
      Java代碼 復(fù)制代碼
      1. @Service
      2. public class ImageFileUpload implements Serializable {
      3. @Properties(name="pic.address" )
      4. private String picAddress;
      5. @Properties(name="pic.url" )
      6. private String picUrl;
      7. private String picServerUrl;
      8. }
      @Service
      public class ImageFileUpload implements Serializable {
      
          @Properties(name="pic.address" )
          private String picAddress;
      
          @Properties(name="pic.url" )
          private String picUrl;
      
          private String picServerUrl;
      }


      pic.address和pic.url是properties文件中的兩個(gè)屬性 

      以上代碼中的@Properties就是我們要實(shí)現(xiàn)的Annotation,通過name的值作為key去對應(yīng)的properties中尋找對應(yīng)的value,并且主動(dòng)賦值給ImageFileUpload的對應(yīng)屬性。 

      3步驟: 
      我們知道,spring在初始化完bean之后我們可以對這些bean進(jìn)行一定的操作,這里就是一個(gè)擴(kuò)展點(diǎn),我決定使用BeanPostProcessor這個(gè)接口,這個(gè)接口中有一個(gè)postProcessAfterInitialization方法就是用來做bean的后處理的,一旦一個(gè)bean被初始化完成之后,我們就可以對這個(gè)bean進(jìn)行賦值了。 

      但是考慮到我們項(xiàng)目中不是所有的bean都使用Annotation來注冊到spring中的,這些普通的,配置在xml文件中的bean也有用到${}的需求,所以我考慮擴(kuò)展PropertyPlaceholderConfigurer這個(gè)類。我們來分析一下具體的代碼。 

      首先建立一個(gè)Annotation,如下: 
      Java代碼 復(fù)制代碼
      1. /**
      2. * @author ahuaxuan(aaron zhang)
      3. * @since 2008-4-7
      4. * @version $Id: Properties.java 261 2008-04-07 07:03:41Z aaron $
      5. */
      6. @Target(ElementType.FIELD)
      7. @Retention(RetentionPolicy.RUNTIME)
      8. public @interface Properties {
      9. // String bundle();
      10. String name();
      11. }
      /**
       * @author ahuaxuan(aaron zhang)
       * @since 2008-4-7
       * @version $Id: Properties.java 261 2008-04-07 07:03:41Z aaron $
       */
      @Target(ElementType.FIELD)
      @Retention(RetentionPolicy.RUNTIME) 
      public @interface Properties {
      
      //	String bundle();
      	
      	String name();
      }


      接著我們實(shí)現(xiàn)我們的擴(kuò)展主類: 
      Java代碼 復(fù)制代碼
      1. /**
      2. * @author ahuaxuan(aaron zhang)
      3. * @since 2008-4-7
      4. * @version $Id: AnnotationBeanPostProcessor.java 260 2008-04-07 07:03:35Z aaron $
      5. */
      6. public class AnnotationBeanPostProcessor extends PropertyPlaceholderConfigurer implements BeanPostProcessor, InitializingBean {
      7. private static transient Log logger = LogFactory.getLog(AnnotationBeanPostProcessor.class);
      8. private java.util.Properties pros;
      9. @SuppressWarnings("unchecked")
      10. private Class[] enableClassList = {String.class};
      11. @SuppressWarnings("unchecked")
      12. public void setEnableClassList(Class[] enableClassList) {
      13. this.enableClassList = enableClassList;
      14. }
      15. public Object postProcessAfterInitialization(Object bean, String beanName)
      16. throws BeansException {
      17. Field [] fields = bean.getClass().getDeclaredFields();
      18. for (Field field : fields) {
      19. if (logger.isDebugEnabled()) {
      20. StringBuilder sb = new StringBuilder();
      21. sb.append(" ========= ")
      22. .append(field.getType())
      23. .append(" ============ ")
      24. .append(field.getName())
      25. .append(" ============ ")
      26. .append(field.isAnnotationPresent(Properties.class));
      27. logger.debug(sb.toString());
      28. }
      29. if (field.isAnnotationPresent(Properties.class)) {
      30. if (filterType(field.getType().toString())) {
      31. Properties p = field.getAnnotation(Properties.class);
      32. try {
      33. // StringBuilder sb = new StringBuilder();
      34. // sb.append("set").append(StringUtils.upperCase(field.getName().substring(0, 1)))
      35. // .append(field.getName().substring(1, field.getName().length()));
      36. //
      37. // Method method = bean.getClass().getMethod(sb.toString(), String.class);
      38. // method.invoke(bean, pros.getProperty(p.name()));
      39. 本來我是通過set方法來把properties文件中的值注入到對應(yīng)的屬性上去的,后來downpour提供了更好的方案,就是下面這兩行代碼,雖然這樣做破壞了private的功能,同時(shí)破壞了封裝,但是確實(shí)節(jié)省了很多代碼,建議大家在業(yè)務(wù)代碼中不要這樣做,如果做框架代碼可以考慮一下。
      40. ReflectionUtils.makeAccessible(field);
      41. field.set(bean, pros.getProperty(p.name()));
      42. catch (Exception e) {
      43. logger.error(" --- ", e);
      44. }
      45. }
      46. }
      47. }
      48. return bean;
      49. }
      50. @SuppressWarnings("unchecked")
      51. private boolean filterType(String type) {
      52. if (type != null) {
      53. for (Class c : enableClassList) {
      54. if (c.toString().equals(type)) {
      55. return true;
      56. }
      57. }
      58. return false;
      59. else {
      60. return true;
      61. }
      62. }
      63. public Object postProcessBeforeInitialization(Object bean, String beanName)
      64. throws BeansException {
      65. return bean;
      66. }
      67. public void afterPropertiesSet() throws Exception {
      68. pros = mergeProperties();
      69. }
      70. }
      /**
       * @author ahuaxuan(aaron zhang)
       * @since 2008-4-7
       * @version $Id: AnnotationBeanPostProcessor.java 260 2008-04-07 07:03:35Z aaron $
       */
      public class AnnotationBeanPostProcessor extends PropertyPlaceholderConfigurer implements BeanPostProcessor, InitializingBean {
      
      	private static transient Log logger = LogFactory.getLog(AnnotationBeanPostProcessor.class);
      	
      	private java.util.Properties pros;
      	
      	@SuppressWarnings("unchecked")
      	private Class[] enableClassList = {String.class};
      	
      	@SuppressWarnings("unchecked")
      	public void setEnableClassList(Class[] enableClassList) {
      		this.enableClassList = enableClassList;
      	}
      
      	public Object postProcessAfterInitialization(Object bean, String beanName)
      			throws BeansException {
      		
      		Field [] fields = bean.getClass().getDeclaredFields();
      		
      		for (Field field : fields) {
      			if (logger.isDebugEnabled()) {
      				StringBuilder sb = new StringBuilder();
      				sb.append(" ========= ")
      					.append(field.getType())
      					.append(" ============ ")
      					.append(field.getName())
      					.append(" ============ ")
      					.append(field.isAnnotationPresent(Properties.class));
      				
      				logger.debug(sb.toString());
      			}
      			
      			if (field.isAnnotationPresent(Properties.class)) {
      				if (filterType(field.getType().toString())) {
      					Properties p = field.getAnnotation(Properties.class);
      					try {
      //						StringBuilder sb = new StringBuilder();
      //						sb.append("set").append(StringUtils.upperCase(field.getName().substring(0, 1)))
      //										.append(field.getName().substring(1, field.getName().length()));
      //						
      //						Method method = bean.getClass().getMethod(sb.toString(), String.class);
      //						method.invoke(bean, pros.getProperty(p.name()));
      本來我是通過set方法來把properties文件中的值注入到對應(yīng)的屬性上去的,后來downpour提供了更好的方案,就是下面這兩行代碼,雖然這樣做破壞了private的功能,同時(shí)破壞了封裝,但是確實(shí)節(jié)省了很多代碼,建議大家在業(yè)務(wù)代碼中不要這樣做,如果做框架代碼可以考慮一下。
      
      						ReflectionUtils.makeAccessible(field);
      						field.set(bean, pros.getProperty(p.name()));
      					} catch (Exception e) {
      						logger.error(" --- ", e);
      					} 
      				}
      			}
      		}
      		
      		
      		return bean;
      	}
      	
      	@SuppressWarnings("unchecked")
      	private boolean filterType(String type) {
      		
      		if (type != null) {
      			for (Class c : enableClassList) {
      				if (c.toString().equals(type)) {
      					return true;
      				}
      			}
      			
      			return false;
      		} else {
      			return true;
      		}
      	}
      
      	public Object postProcessBeforeInitialization(Object bean, String beanName)
      			throws BeansException {
      		return bean;
      	}
      
      	public void afterPropertiesSet() throws Exception {
      		pros = mergeProperties();
      	}
      }


      最后我們需要在xml文件中配置一下: 
      Java代碼 復(fù)制代碼
      1. <bean id="propertyConfigurer"
      2. class="xx.service.AnnotationBeanPostProcessor">
      3. <property name="locations">
      4. <list>
      5. <value>classpath:jdbc.properties</value>
      6. </list>
      7. </property>
      8. </bean>
      <bean id="propertyConfigurer"
      		class="xx.service.AnnotationBeanPostProcessor">
      		<property name="locations">
      			<list>
      				<value>classpath:jdbc.properties</value>
      			</list>
      		</property>
      	</bean>


      這樣任何一個(gè)bean,不管它是使用annotation注冊的,還是直接配置在xml文件中的都可以使用這種方式來注入properties中的值。 

      下面看一下我在項(xiàng)目中的一個(gè)真實(shí)的例子,這個(gè)類是一個(gè)value object,它代表一組配置: 
      Java代碼 復(fù)制代碼
      1. @Component
      2. public class Config implements Serializable{
      3. /** */
      4. private static final long serialVersionUID = 8737228049639915113L;
      5. @Properties(name = " online.pay.accounts")
      6. private String accounts;
      7. @Properties(name = " online.pay.user")
      8. private String user;
      9. @Properties(name = " online.pay.password")
      10. private String password;
      11. @Properties(name = " online.transurl")
      12. private String transUrl;
      13. @Properties(name = " online.refundurl")
      14. private String refundUrl;
      15. @Properties(name = " online.query")
      16. private String queryUrl;
      17. ```setter and getter method
      18. }
      @Component
      public class Config implements Serializable{
      
      	/**  */
      	private static final long serialVersionUID = 8737228049639915113L;
      
      	@Properties(name = " online.pay.accounts")
      	private String accounts;
      	
      	@Properties(name = " online.pay.user")
      	private String user;
      	
      	@Properties(name = " online.pay.password")
      	private String password;
      	
      	@Properties(name = " online.transurl")
      	private String transUrl;
      	
      	@Properties(name = " online.refundurl")
      	private String refundUrl;
      	
      	@Properties(name = " online.query")
      	private String queryUrl;
      
      	```setter and getter method
      }
      

      那么在需要用到該vo的地方比如: 
      Java代碼 復(fù)制代碼
      1. @Service(“userService”)
      2. public class UserServiceImpl implements UserService {
      3. @autowired
      4. private Config config;
      5. public void setConfig(Config config) {
      6. This.config = config;
      7. }
      8. }
      @Service(“userService”)
      public class UserServiceImpl implements UserService {
      	@autowired
      	private Config config;
      
      	public void setConfig(Config config) {
      		This.config = config;
      	}
      }

      就這么多內(nèi)容就ok了,如果按照原來的辦法,我們就需要在xml配置以上兩個(gè)bean,然后在里面寫一堆又一堆的${},肯定能讓你看了之后崩潰,至少我差點(diǎn)崩潰,因?yàn)樗瓷先?shí)在是太丑陋了。而現(xiàn)在,我的心情好多了,因?yàn)槲矣眠@個(gè)@Properties(name = "")用的很爽,呵呵,而且即使有些bean是配置在xml文件中的,比如datasource等等,我們還是可以通過${}來進(jìn)行設(shè)值,也就是說這個(gè)方案既支持annotation,也支持${},很好,很強(qiáng)大。 

      結(jié)語: 
      很顯然,在spring2.5的時(shí)代,以上這個(gè)需求是非常平常的,我相信在spring3.0中一定會提供這樣的功能,而且我覺得spring2.5應(yīng)該是一個(gè)過渡版本,雖然上面的方案中代碼行數(shù)并不多,但是我覺得很有價(jià)值,應(yīng)該很有市場才對,也許我們可以把這個(gè)東東叫做spring-properties2object-plugin。 

      題外話: 
      說點(diǎn)題外話吧,目前在我的項(xiàng)目里,我使用了struts2.0+spring2.5+hibernate3.2,使用struts2.0的時(shí)候我使用struts2.0的zero configuration和codebehind,基本上實(shí)現(xiàn)了真正意義零配置,剩下的都是一些common的配置,而且很少,不超過150行。在使用spring的時(shí)候,我也基本上是使用annotation來注冊我的bean,同時(shí)使用上面的方案來作為補(bǔ)充,所以applicationContext-xxx.xml中的也是一些common的配置,也是非常少,應(yīng)該只有200行左右。而hibernate我是使用annotation來配置我的PO,基本沒有配置文件。所以整個(gè)項(xiàng)目的xml文件中配置的總行數(shù)大大下降。 

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多