您的位置:首页 > 编程语言 > PHP开发

使用BeanPostProcessor接口对受管Bean进行预处理,通过自定义Annotation,获取所有Controller的Url

2013-01-30 16:25 851 查看
有时候,我们希望在Spring IoC容器初始化受管Bean之前、属性设置之后对该Bean先做一些预处理,或者在容器销毁受管Bean之前自己释放资源。那么该如何实现呢?Spring
IoC为我们提供了多种方法来实现受管Bean的预处理和后处理。

在Spring中定义了BeanPostProcessors接口。

项目实例:在项目中获取部分Controller的Url

1、自定义Annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Function {
String name() default "";
String description() default "";
}


2、在需要获取Url的Controller上加上自定义Annotation

@RequestMapping(method = RequestMethod.GET)
@Function(name = "文件发送", description = "政企通-文件发送")
public String send(HttpServletRequest request,ModelMap model) throws ServletRequestBindingException {
User user = (User) Application.getCurrentUserInfo().getCurrentUser();
List<UserComGroup> userComGroups = userComGroupManager.query().filterEqual("user", user).list();
super.storeRequestParams(model);
model.put("userComGroups", userComGroups);
return view("send");
}


3、解析Annotation里面的内容

public class RouterInfo {
private String beanName;
private String beanClass;
private String invokeMethod;
private String requestMethod;
private String url;
...
}


public class FunctionInfo extends RouterInfo{

//功能名称
private String name;
//功能描述
private String description;
...
}


public class FunctionInfoCollector implements BeanInfoCollector<FunctionInfo> {
private List<FunctionInfo> functionInfos = Lists.newArrayList();

public void collect(Object bean, String beanName) {
final Class<?> beanClazz = bean.getClass();
if (beanClazz.isAnnotationPresent(Controller.class)) {
for(Method method : beanClazz.getMethods()) {
if (method.isAnnotationPresent(Function.class)
&& method.isAnnotationPresent(RequestMapping.class)) {
Function function = method.getAnnotation(Function.class);
if (function != null) {
Map<String, MethodInfo> urls = determineUrlsForHandler(bean,
beanName);
for (Map.Entry<String, MethodInfo> entry : urls.entrySet()) {
MethodInfo methodInfo = entry.getValue();
if(methodInfo.invokeMethod.equals(method.getName())) {
functionInfos.add(new FunctionInfo(function.name(), function.description(), beanName, beanClazz.getName(),
methodInfo.invokeMethod, methodInfo.requestMethod, methodInfo.url));
}
}
}
}
}
}
}

public List<FunctionInfo> getBeanInfos() {
return Collections.unmodifiableList(functionInfos);
}

protected Map<String, MethodInfo> determineUrlsForHandler(Object bean,
String beanName) {
Class<?> handlerType = bean.getClass();
RequestMapping mapping = handlerType
.getAnnotation(RequestMapping.class);
if (mapping != null) {
// @RequestMapping found at type level
Map<String, MethodInfo> urls = new LinkedHashMap<String, MethodInfo>();
String[] typeLevelPatterns = mapping.value();
if (typeLevelPatterns.length > 0) {
// @RequestMapping specifies paths at type level
Map<String, MethodInfo> methodLevelPatterns = determineUrlsForHandlerMethods(
handlerType, true);
for (String typeLevelPattern : typeLevelPatterns) {
if (!typeLevelPattern.startsWith("/")) {
typeLevelPattern = "/" + typeLevelPattern;
}
for (Map.Entry<String, MethodInfo> entry : methodLevelPatterns
.entrySet()) {
final MethodInfo methodInfo = entry.getValue();
String methodLevelPattern = methodInfo.getUrl();
if (methodLevelPattern != null) {
String combinedPattern = getPathMatcher().combine(
typeLevelPattern, methodLevelPattern);
addUrlsForPath(urls, methodInfo.getInvokeMethod(),
methodInfo.getRequestMethod(),
combinedPattern);
}
}
}
return urls;
} else {
// actual paths specified by @RequestMapping at method level
return determineUrlsForHandlerMethods(handlerType, false);
}
} else if (AnnotationUtils
.findAnnotation(handlerType, Controller.class) != null) {
// @RequestMapping to be introspected at method level
return determineUrlsForHandlerMethods(handlerType, false);
} else {
return null;
}
}

private String getRequestMethod(RequestMapping mapping) {
if (mapping.method().length == 0) {
return "*";
}
StringBuilder sb = new StringBuilder();
RequestMethod[] requestMethods = mapping.method();
for (int i = 0; i < requestMethods.length; i++) {
if (i != 0) {
sb.append(" | ");
}
sb.append(requestMethods[i]);
}
return sb.toString();
}

private PathMatcher getPathMatcher() {
return new AntPathMatcher();
}

protected Map<String, MethodInfo> determineUrlsForHandlerMethods(
Class<?> handlerType, final boolean hasTypeLevelMapping) {
Map<String, MethodInfo> subclassResult = determineUrlsForHandlerMethods(handlerType);
if (subclassResult != null) {
return subclassResult;
}

final Map<String, MethodInfo> urls = new LinkedHashMap<String, MethodInfo>();
Class<?>[] handlerTypes = Proxy.isProxyClass(handlerType) ? handlerType
.getInterfaces() : new Class<?>[] { handlerType };
for (Class<?> currentHandlerType : handlerTypes) {
ReflectionUtils.doWithMethods(currentHandlerType,
new ReflectionUtils.MethodCallback() {
public void doWith(Method method) {
RequestMapping mapping = AnnotationUtils
.findAnnotation(method,
RequestMapping.class);
final String methodName = method.getName();
if (mapping != null) {
String[] mappedPatterns = mapping.value();
if (mappedPatterns.length > 0) {
for (String mappedPattern : mappedPatterns) {
if (!hasTypeLevelMapping
&& !mappedPattern
.startsWith("/")) {
mappedPattern = "/" + mappedPattern;
}

addUrlsForPath(urls, methodName,
getRequestMethod(mapping),
mappedPattern);
}
} else if (hasTypeLevelMapping) {
// empty method-level RequestMapping
addUrlsForPath(urls, methodName,
getRequestMethod(mapping), "");
}
}
}
}, ReflectionUtils.NON_BRIDGED_METHODS);
}
return urls;
}

protected Map<String, MethodInfo> determineUrlsForHandlerMethods(
Class<?> handlerType) {
return null;
}

protected void addUrlsForPath(Map<String, MethodInfo> urls,
String invokeMethod, String requestMethod, String path) {
String url = path;

}

urls.put(invokeMethod, new MethodInfo(invokeMethod, requestMethod, url));
}

private static class MethodInfo {
private final String invokeMethod;
private final String requestMethod;
private final String url;

public MethodInfo(String invokeMethod, String requestMethod, String url) {
this.invokeMethod = invokeMethod;
this.requestMethod = requestMethod;
this.url = url;
}

public String getInvokeMethod() {
return invokeMethod;
}

public String getRequestMethod() {
return requestMethod;
}

public String getUrl() {
return url;
}

}
}


4、定义了BeanPostProcessors进行预处理

@Configuration:与Spring配置文件(application-config.xml)配置bean类似

@Configuration
public class MainConfig {
private AnnotationSessionFactoryBean annotationSessionFactoryBean;

@Inject
public void setAnnotationSessionFactoryBean(
AnnotationSessionFactoryBean annotationSessionFactoryBean) {
this.annotationSessionFactoryBean = annotationSessionFactoryBean;
}

@Bean(name = "systemInfoBeanPostProcessor")
public BeanPostProcessor systemInfoBeanPostProcessor() {
return new BeanInfoCollectorBeanPostProcessor().addBeanInfoCollector(functionInfoCollector());
}

@Bean(name = "functionInfoCollector")
public FunctionInfoCollector functionInfoCollector() {
return new FunctionInfoCollector();
}

public static class BeanInfoCollectorBeanPostProcessor implements
BeanPostProcessor {//实现BeanPostProcessor接口
private static Logger logger = LoggerFactory
.getLogger(BeanInfoCollectorBeanPostProcessor.class);

private final List<BeanInfoCollector<?>> beanInfoCollectors = new ArrayList<BeanInfoCollector<?>>();

public Object postProcessBeforeInitialization(Object bean,
String beanName) {
return bean;
}

public Object postProcessAfterInitialization(Object bean,
String beanName) {
for (BeanInfoCollector<?> collector : beanInfoCollectors) {
try {
collector.collect(bean, beanName);
} catch (Exception e) {
logger.warn("BeanInfoCollector " + collector + "执行出错!", e);
}
}

return bean;
}

public <T> void setBeanInfoCollectors(
List<BeanInfoCollector<T>> beanInfoCollectors) {
this.beanInfoCollectors.addAll(beanInfoCollectors);
}

public <T> BeanInfoCollectorBeanPostProcessor addBeanInfoCollector(
BeanInfoCollector<T> beanInfoCollector) {
beanInfoCollectors.add(beanInfoCollector);
return this;
}

}
}


5、获取url数据

@Inject
private FunctionInfoCollector functionInfoCollector;

public String index(ModelMap model) throws ServletRequestBindingException {
List<FunctionInfo> functionInfos = functionInfoCollector.getBeanInfos();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐