对spring做java注解扩展

在开发Java程序,尤其是Java EE应用的时候,总是免不了与各种配置文件打交道。java注解则帮我们使之更整洁,不会配置文件满天飞了。
今天我写了一个简单的对spring做了扩展的注解,它的主要功能就是将配置文件里的属性赋值到你需要的地方。(建议在看该例子之前搜下注解的基础知识,熟悉下)
首先,写一个@PropertyConfig注解

package com.inigo.annotation.annotation.spring.exetend;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface PropertyConfig {
String value() default "";

boolean required() default true;
}

我们会发现,定义一个注解很像定义接口一样,里面的类似方法的东西就是声明了一个配置参数了。用的时候@PropertyConfig 或者@PropertyConfig("username")或者@PropertyConfig(value="username")
然后,要重写org.springframework.beans.factory.config.PropertyPlaceholderConfigurer这个类了,为的是取出spring读取到的配置文件里的属性

package com.inigo.annotation.annotation.spring.exetend;

import java.util.Properties;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.stereotype.Component;

@Component
public class ExtendedPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private Properties props;

@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
super.processProperties(beanFactory, props);
this.props = props;
}

public Object getProperty(String key) {
return props.get(key);
}
}

这个类代码很简单,不必多说
注意配置spring的配置文件的时候要用这个类来取配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-autowire="byName" default-lazy-init="false">
<!-- 属性文件读入-->
<bean id="propertyConfigurer"
class="com.inigo.annotation.annotation.spring.exetend.ExtendedPropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath*:/application.properties</value>
</list>
</property>
</bean>
<context:component-scan base-package="com.inigo.annotation.annotation.spring.exetend" />
<context:component-scan base-package="com.inigo.annotation.service" />
<context:annotation-config/>
</beans>

再次,就是很重要的对注解进行处理的类了

package com.inigo.annotation.annotation.spring.exetend;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import org.springframework.beans.BeansException;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

@Component
public class ConfigAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Autowired
private ExtendedPropertyPlaceholderConfigurer propertyConfigurer;

private SimpleTypeConverter typeConverter = new SimpleTypeConverter();

/**
* <p>通过config配置变量,bean初始化以后设置properties文件里面的值</p>
* {@inheritDoc}
*/
@Override
public boolean postProcessAfterInstantiation(final Object bean, String beanName) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
PropertyConfig cfg = field.getAnnotation(PropertyConfig.class);
if (cfg != null) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@PropertyConfig annotation is not supported on static fields");
}

String key = cfg.value().length() <= 0 ? field.getName() : cfg.value();
Object value = propertyConfigurer.getProperty(key);
if (cfg.required() && value == null) {
throw new NullPointerException(bean.getClass().getSimpleName() + "." + field.getName()
+ " is requred,but not been configured");
} else if (value != null) {
Object _value = typeConverter.convertIfNecessary(value, field.getType());
ReflectionUtils.makeAccessible(field);
field.set(bean, _value);
}
}
}
});
return true;
}
}

在这里面我们会有一个小处理,就是当注解没有写value的时候,默认用field.getName()来当做key去取properties了
接着,还要有一个简单类来用下这个注解

package com.inigo.annotation.service;

import org.springframework.stereotype.Component;

import com.inigo.annotation.annotation.spring.exetend.PropertyConfig;


@Component
public class TestService {
@PropertyConfig
private String username;
@PropertyConfig
private String password;

public void testMethod() {
System.out.println("Annotation begin");
System.out.println("username:" + username);
System.out.println("password:" + password);
}

}

最后,就是用spring容器生成这个TestService类来测试下效果了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值