- 浏览: 853460 次
文章分类
- 全部博客 (365)
- java (124)
- spring mvc (21)
- spring (22)
- struts2 (6)
- jquery (27)
- javascript (24)
- mybatis/ibatis (8)
- hibernate (7)
- compass (11)
- lucene (26)
- flex (0)
- actionscript (0)
- webservice (8)
- rabbitMQ/Socket (15)
- jsp/freemaker (5)
- 数据库 (27)
- 应用服务器 (21)
- Hadoop (1)
- PowerDesigner (3)
- EJB (0)
- JPA (0)
- PHP (2)
- C# (0)
- .NET (0)
- html (2)
- xml (5)
- android (7)
- flume (1)
- zookeeper (0)
- 证书加密 (2)
- maven (1)
- redis (2)
- cas (11)
最新评论
-
zuxianghuang:
通过pom上传报错 Artifact upload faile ...
nexus上传了jar包.通过maven引用当前jar,不能取得jar的依赖 -
流年末年:
百度网盘的挂了吧???
SSO单点登录系列3:cas-server端配置认证方式实践(数据源+自定义java类认证) -
953434367:
UfgovDBUtil 是什么类
Java发HTTP POST请求(内容为xml格式) -
smilease:
帮大忙了,非常感谢
freemaker自动生成源代码 -
syd505:
十分感谢作者无私的分享,仔细阅读后很多地方得以解惑。
Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解
1、struts2作用域:每一个Action我们必须设置scope为prototype 每次都做重复的配置,而且有时候忘记配置还会出现bug,想不想删掉它?
<bean id="**Action" class="***Action" scope="prototype">
2、在使用spring集成hibernate时,每次都必须注入sessionFactory,虽然可以用父子bean解决 但还是要写parent="abstractHibernateDao"之类的。
<bean id="***Dao" class="***DaoImpl">
<property name="sessionFactory" ref="sessionFactory">
</bean>
受够了这种配置,得想法解决这个重复配置,怎么解决呢?
思路:
在BeanFactory创建Bean之前查找所有我们需要通用化配置的Bean 然后修改BeanDefinition注入我们的通用数据就可以解决我们这个问题。
Spring提供了BeanFactoryPostProcessor扩展点,用于提供给我们修改BeanDefinition数据的。
还记得org.springframework.beans.factory.config.PropertyPlaceholderConfigurer吗? 替换占位符数据,它就是一个BeanFactoryPostProcessor的实现。
好了思路有了,接下来我们实现一下吧:
1、XML配置方式
*
* 使用方法:<br/>
* <pre>
* <bean class="cn.javass.common.spring.CommonConfigureProcessor">
<property name="config">
<map>
<!-- aspectj表达式 选择所有Action结尾的Bean 注入scope数据 为 prototype -->
<entry key="cn.javass..*Action">
<props>
<prop key="scope">prototype</prop>
</props>
</entry>
<!-- aspectj表达式 选择所有的HibernateDaoSupport实现Bean 注入sessionFactory -->
<entry key="org.springframework.orm.hibernate3.support.HibernateDaoSupport+">
<props>
<prop key="property-ref">sessionFactory=sessionFactory</prop>
</props>
</entry>
</map>
</property>
</bean>
* </pre>
*
* 目前支持三种配置:
* scope:注入作用域
* property-ref:注入Bean引用 如之上的sessionFactory
* propertyName=beanName
* property-value:注入常量值
* propertyName=常量
2、CommonConfigureProcessor源码
- package cn.javass.common.spring;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Properties;
- import org.aspectj.bridge.IMessageHandler;
- import org.aspectj.weaver.ResolvedType;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.bcel.BcelWorld;
- import org.aspectj.weaver.patterns.Bindings;
- import org.aspectj.weaver.patterns.FormalBinding;
- import org.aspectj.weaver.patterns.IScope;
- import org.aspectj.weaver.patterns.PatternParser;
- import org.aspectj.weaver.patterns.SimpleScope;
- import org.aspectj.weaver.patterns.TypePattern;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.config.RuntimeBeanNameReference;
- import org.springframework.beans.factory.config.RuntimeBeanReference;
- import org.springframework.util.StringUtils;
- /**
- *
- * 设置通用配置<br/>
- *
- * 使用方法:<br/>
- * <pre>
- * <bean class="cn.javass.common.spring.CommonConfigureProcessor">
- <property name="config">
- <map>
- <!-- aspectj表达式 选择所有Action结尾的Bean 注入scope数据 为 prototype -->
- <entry key="cn.javass..*Action">
- <props>
- <prop key="scope">prototype</prop>
- </props>
- </entry>
- <!-- aspectj表达式 选择所有的HibernateDaoSupport实现Bean 注入sessionFactory -->
- <entry key="org.springframework.orm.hibernate3.support.HibernateDaoSupport+">
- <props>
- <prop key="property-ref">sessionFactory=sessionFactory</prop>
- </props>
- </entry>
- </map>
- </property>
- </bean>
- * </pre>
- *
- * 目前支持三种配置:
- * scope:注入作用域
- * property-ref:注入Bean引用 如之上的sessionFactory
- * propertyName=beanName
- * property-value:注入常量值
- * propertyName=常量
- *
- * @author Zhangkaitao
- * @version 1.0
- *
- */
- public class CommonConfigureProcessor implements BeanFactoryPostProcessor {
- private Logger log = LoggerFactory.getLogger(CommonConfigureProcessor.class);
- private Map<String, Properties> config = new HashMap<String, Properties>();
- public void setConfig(Map<String, Properties> config) {
- this.config = config;
- }
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
- log.debug("apply common config start");
- for(Entry<String, Properties> entry : config.entrySet()) {
- String aspectjPattern = entry.getKey();
- Properties props = entry.getValue();
- List<BeanDefinition> bdList = findBeanDefinition(aspectjPattern, factory);
- apply(bdList, props);
- }
- log.debug("apply common config end");
- }
- private void apply(List<BeanDefinition> bdList, Properties props) {
- for(Entry<Object, Object> entry : props.entrySet()) {
- String key = (String) entry.getKey();
- String value = (String) entry.getValue();
- switch(SupportedConfig.keyToEnum(key)) {
- case scope :
- applyScope(bdList, value);
- break;
- case propertyRef:
- applyPropertyRef(bdList, value);
- break;
- case propertyValue:
- applyPropertyValue(bdList, value);
- break;
- default:
- throw new IllegalArgumentException(String.format("错误的配置:[%s]", key));
- }
- }
- }
- private void applyPropertyValue(List<BeanDefinition> bdList, String value) {
- for(BeanDefinition bd : bdList) {
- String propertyName = value.split("=")[0];
- String propertyValue = value.substring(propertyName.length()+1);
- bd.getPropertyValues().add(propertyName, propertyValue);
- log.debug("apply property value {} to {}", value, bd.getBeanClassName());
- }
- }
- private void applyPropertyRef(List<BeanDefinition> bdList, String value) {
- for(BeanDefinition bd : bdList) {
- String propertyName = value.split("=")[0];
- String propertyValue = value.substring(propertyName.length()+1);
- bd.getPropertyValues().addPropertyValue(propertyName, new RuntimeBeanReference(propertyValue));
- log.debug("apply property ref {} to {}", value, bd.getBeanClassName());
- }
- }
- private void applyScope(List<BeanDefinition> bdList, String value) {
- for(BeanDefinition bd : bdList) {
- bd.setScope(value);
- log.debug("apply scope {} to {}", value, bd.getBeanClassName());
- }
- }
- private List<BeanDefinition> findBeanDefinition(String aspectjPattern, ConfigurableListableBeanFactory factory) {
- List<BeanDefinition> bdList = new ArrayList<BeanDefinition>();
- for(String beanName : factory.getBeanDefinitionNames()) {
- BeanDefinition bd = factory.getBeanDefinition(beanName);
- if(matches(aspectjPattern, bd.getBeanClassName())) {
- bdList.add(bd);
- }
- }
- return bdList;
- }
- private boolean matches(String aspectjPattern, String beanClassName) {
- if(!StringUtils.hasLength(beanClassName)) {
- return false;
- }
- return new AspectJTypeMatcher(aspectjPattern).matches(beanClassName);
- }
- //支持的操作
- private static enum SupportedConfig {
- scope("scope"),
- propertyRef("property-ref"),
- propertyValue("property-value"),
- error("error"); //出错的情况
- private final String key;
- private SupportedConfig(String key) {
- this.key = key;
- }
- public static SupportedConfig keyToEnum(String key) {
- if(key == null) {
- return error;
- }
- for(SupportedConfig config : SupportedConfig.values()) {
- if(config.key.equals(key.trim())) {
- return config;
- }
- }
- return error;
- }
- }
- public static interface TypeMatcher {
- public boolean matches(String className);
- }
- static class AspectJTypeMatcher implements TypeMatcher {
- private final World world;
- private final TypePattern typePattern;
- public AspectJTypeMatcher(String pattern) {
- this.world = new BcelWorld(Thread.currentThread().getContextClassLoader(), IMessageHandler.THROW, null);
- this.world.setBehaveInJava5Way(true);
- PatternParser patternParser = new PatternParser(pattern);
- TypePattern typePattern = patternParser.parseTypePattern();
- typePattern.resolve(this.world);
- IScope scope = new SimpleScope(this.world, new FormalBinding[0]);
- this.typePattern = typePattern.resolveBindings(scope, Bindings.NONE, false, false);
- }
- @Override
- public boolean matches(String className) {
- ResolvedType resolvedType = this.world.resolve(className);
- return this.typePattern.matchesStatically(resolvedType);
- }
- }
- public static void main(String[] args) {
- //System.out.println(new AspectJTypeMatcher("cn.javass..*Action").matches("cn.javass.test.web.action.AbcAction"));
- //System.out.println(new AspectJTypeMatcher("com.opensymphony.xwork2.ActionSupport+").matches("cn.javass.erp.web.action.MoneyAction"));
- }
- }
package cn.javass.common.spring; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.aspectj.bridge.IMessageHandler; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.World; import org.aspectj.weaver.bcel.BcelWorld; import org.aspectj.weaver.patterns.Bindings; import org.aspectj.weaver.patterns.FormalBinding; import org.aspectj.weaver.patterns.IScope; import org.aspectj.weaver.patterns.PatternParser; import org.aspectj.weaver.patterns.SimpleScope; import org.aspectj.weaver.patterns.TypePattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.RuntimeBeanNameReference; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.util.StringUtils; /** * * 设置通用配置<br/> * * 使用方法:<br/> * <pre> * <bean class="cn.javass.common.spring.CommonConfigureProcessor"> <property name="config"> <map> <!-- aspectj表达式 选择所有Action结尾的Bean 注入scope数据 为 prototype --> <entry key="cn.javass..*Action"> <props> <prop key="scope">prototype</prop> </props> </entry> <!-- aspectj表达式 选择所有的HibernateDaoSupport实现Bean 注入sessionFactory --> <entry key="org.springframework.orm.hibernate3.support.HibernateDaoSupport+"> <props> <prop key="property-ref">sessionFactory=sessionFactory</prop> </props> </entry> </map> </property> </bean> * </pre> * * 目前支持三种配置: * scope:注入作用域 * property-ref:注入Bean引用 如之上的sessionFactory * propertyName=beanName * property-value:注入常量值 * propertyName=常量 * * @author Zhangkaitao * @version 1.0 * */ public class CommonConfigureProcessor implements BeanFactoryPostProcessor { private Logger log = LoggerFactory.getLogger(CommonConfigureProcessor.class); private Map<String, Properties> config = new HashMap<String, Properties>(); public void setConfig(Map<String, Properties> config) { this.config = config; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException { log.debug("apply common config start"); for(Entry<String, Properties> entry : config.entrySet()) { String aspectjPattern = entry.getKey(); Properties props = entry.getValue(); List<BeanDefinition> bdList = findBeanDefinition(aspectjPattern, factory); apply(bdList, props); } log.debug("apply common config end"); } private void apply(List<BeanDefinition> bdList, Properties props) { for(Entry<Object, Object> entry : props.entrySet()) { String key = (String) entry.getKey(); String value = (String) entry.getValue(); switch(SupportedConfig.keyToEnum(key)) { case scope : applyScope(bdList, value); break; case propertyRef: applyPropertyRef(bdList, value); break; case propertyValue: applyPropertyValue(bdList, value); break; default: throw new IllegalArgumentException(String.format("错误的配置:[%s]", key)); } } } private void applyPropertyValue(List<BeanDefinition> bdList, String value) { for(BeanDefinition bd : bdList) { String propertyName = value.split("=")[0]; String propertyValue = value.substring(propertyName.length()+1); bd.getPropertyValues().add(propertyName, propertyValue); log.debug("apply property value {} to {}", value, bd.getBeanClassName()); } } private void applyPropertyRef(List<BeanDefinition> bdList, String value) { for(BeanDefinition bd : bdList) { String propertyName = value.split("=")[0]; String propertyValue = value.substring(propertyName.length()+1); bd.getPropertyValues().addPropertyValue(propertyName, new RuntimeBeanReference(propertyValue)); log.debug("apply property ref {} to {}", value, bd.getBeanClassName()); } } private void applyScope(List<BeanDefinition> bdList, String value) { for(BeanDefinition bd : bdList) { bd.setScope(value); log.debug("apply scope {} to {}", value, bd.getBeanClassName()); } } private List<BeanDefinition> findBeanDefinition(String aspectjPattern, ConfigurableListableBeanFactory factory) { List<BeanDefinition> bdList = new ArrayList<BeanDefinition>(); for(String beanName : factory.getBeanDefinitionNames()) { BeanDefinition bd = factory.getBeanDefinition(beanName); if(matches(aspectjPattern, bd.getBeanClassName())) { bdList.add(bd); } } return bdList; } private boolean matches(String aspectjPattern, String beanClassName) { if(!StringUtils.hasLength(beanClassName)) { return false; } return new AspectJTypeMatcher(aspectjPattern).matches(beanClassName); } //支持的操作 private static enum SupportedConfig { scope("scope"), propertyRef("property-ref"), propertyValue("property-value"), error("error"); //出错的情况 private final String key; private SupportedConfig(String key) { this.key = key; } public static SupportedConfig keyToEnum(String key) { if(key == null) { return error; } for(SupportedConfig config : SupportedConfig.values()) { if(config.key.equals(key.trim())) { return config; } } return error; } } public static interface TypeMatcher { public boolean matches(String className); } static class AspectJTypeMatcher implements TypeMatcher { private final World world; private final TypePattern typePattern; public AspectJTypeMatcher(String pattern) { this.world = new BcelWorld(Thread.currentThread().getContextClassLoader(), IMessageHandler.THROW, null); this.world.setBehaveInJava5Way(true); PatternParser patternParser = new PatternParser(pattern); TypePattern typePattern = patternParser.parseTypePattern(); typePattern.resolve(this.world); IScope scope = new SimpleScope(this.world, new FormalBinding[0]); this.typePattern = typePattern.resolveBindings(scope, Bindings.NONE, false, false); } @Override public boolean matches(String className) { ResolvedType resolvedType = this.world.resolve(className); return this.typePattern.matchesStatically(resolvedType); } } public static void main(String[] args) { //System.out.println(new AspectJTypeMatcher("cn.javass..*Action").matches("cn.javass.test.web.action.AbcAction")); //System.out.println(new AspectJTypeMatcher("com.opensymphony.xwork2.ActionSupport+").matches("cn.javass.erp.web.action.MoneyAction")); } }
此类只实现基本的通用配置,欢迎大家提供想法并完善这个工具类。
发表评论
-
Spring事务的传播行为和隔离级别
2015-01-23 09:15 601Spring事务的传播行为和隔离级别[transaction ... -
jackson annotations注解详解
2015-01-13 11:34 18995官方WIKI:https://github.com/Fast ... -
Spring3.2.8+Mybatis3.2.6+Maven 整合配置
2015-01-06 14:01 1441 -
采用AOP+log4j记录项目日志
2014-10-28 16:39 490关于AOP,我之前对AOP ... -
Spring Security3.1实践
2014-05-07 14:45 1014说明下: 本篇博客时间久远,数 ... -
SpringMVC3.0+MyIbatis3.0(分页示例)
2013-10-30 17:24 2223参考资料 1 ibatis2.x与mybatis ... -
网上的一篇spring security详解教程,觉得不错,转过来了
2013-07-30 22:16 1355先来谈一谈Acegi的基础知识,Acegi的架构比较复杂,但 ... -
Spring Security3配置使用
2013-07-30 16:48 3496使用Spring Security3的 ... -
SSH项目中加入spring security(二)--加入自定义数据表
2013-07-30 13:32 1025上一篇中基本的spring security已经加入到项 ... -
SSH项目中加入spring security(一)
2013-07-30 13:30 1576很久没有写过博客了,最近项目中 ... -
Spring定时任务的几种实现
2013-01-22 18:27 855近日项目开发中需要执行一些定时任务,比如需要在 ... -
spring security权限管理手册升级至spring security-3.1.3
2012-12-08 12:57 1965企业应用 费了半天劲,终于把原来基于spri ... -
在Spring、Hibernate中使用Ehcache缓存
2012-11-02 21:49 923前一篇http://www.blogjava.n ... -
Ehcache 整合Spring 使用页面、对象缓存
2012-11-02 19:56 1107Ehcache在很多项目中都出现过,用法也比较简 ... -
Spring 3.1 M1 中的缓存功能
2012-11-02 19:26 829本文转自:http://www.oschina.net/ ... -
深入剖析Spring Web源码(八) - 处理器映射,处理器适配器以及处理器的实现 - 基于简单控制器流程的实现
2012-10-31 13:37 13271.1.1.1 ... -
spring 源码 阅读 笔记 之 HandlerMapping
2012-10-31 12:59 1678SpringCVSBeanHTMLAnt ... -
spring mvc重复提交拦截器方法
2012-10-31 11:37 9017import javax.servlet.http.HttpS ... -
Ehcache 整合Spring 使用页面、对象缓存
2012-10-16 09:44 788Ehcache在很多项目中都出现过,用法也比较简单。一般的 ... -
SpringMVC文件上传 多文件
2012-10-15 17:27 7087必须明确告诉DispatcherServlet如何处理Mult ...
相关推荐
AOP允许我们将日志、事务管理、安全检查等通用功能作为“切面”独立处理,避免了在多个类中重复编写相同代码。切面通过定义切入点(Pointcut)和通知(Advice)来实现,Spring提供了多种通知类型,如前置通知、后置...
- **容器**:Spring提供了两种类型的容器——BeanFactory和ApplicationContext,它们都实现了工厂模式,用于实例化、定位和配置对象或bean。 - **MVC框架**:Spring提供了一个轻量级的MVC框架,方便快速地开发Web...
通过AOP,我们可以定义横切关注点,如日志记录、事务管理等,将这些通用逻辑抽取出来,避免在每个业务方法中重复编写。Spring AOP支持使用注解和XML配置两种方式定义切面,大大提高了代码的可读性和可维护性。 最后...
例如,日志、事务管理等通用功能可以通过切面实现,减少代码重复,提高代码结构清晰度。 3. **IoC容器**:Spring的核心组件,负责管理对象的生命周期和装配。容器读取配置元数据,创建并管理对象,通过依赖注入将...
3. **AOP**:面向切面编程允许开发者将关注点分离,例如日志、事务管理等,可以编写一次,然后在整个应用中通用,减少代码重复。 二、Spring MVC 1. **Model-View-Controller**:Spring MVC 是 Spring 框架的一...
【知识点详解】 在软件开发中,特别是在企业级应用中,数据管理是一个重要的环节。CRUD(Create, Read, Update, Delete)...使用Spring Boot的AOP特性,我们可以高效地实现这一目标,使得CRUD操作更加智能化和自动化。
Spring框架中的AOP(面向方面编程)是其核心特性之一,它是对传统面向对象编程(OOP)的一种补充,用于解决横切关注点的问题,即那些在多个类中重复出现的非核心业务逻辑,如事务管理、日志记录、安全性等。...
**mica:云母——Spring Cloud微服务开发的核心包** mica,取名自云母,是一种在Spring Cloud生态中的微服务开发核心工具集。它为开发者提供了丰富的基础工具类和组件,使得在构建分布式系统时能够更加高效、便捷。...
此外,对于那些通用但需要特殊处理的部分,开发者可以保留接口不生成具体的实现,留待后期根据业务逻辑自行编写。 在Spring框架中,代码生成工具可以生成Service和Controller层的代码,为服务调用和视图展示提供...
- `spring-aop.jar`:此文件包含了Spring的AOP模块,提供了面向切面的编程实现,允许开发者在不修改源代码的情况下,对方法进行拦截和增强,如日志记录、事务管理等。 - `spring-context.jar`:这是Spring框架的...
本主题主要关注的是“templates”——一组用于避免记忆大量无用配置设置的通用模板,尤其与Java编程语言相关。 标题“templates:一组通用模板,以避免记住无用的配置设置”揭示了这个资源的核心价值。这里的...
SSM企业级开发框架是Java领域中常用的三大框架——Spring、SpringMVC和MyBatis的集成,广泛应用于Web应用的开发。这个压缩包提供的内容是基于MySQL数据库的SSM框架实现,适用于学习和理解企业级开发流程。下面将详细...
通过定义切面、通知和切入点,我们可以将这些通用功能模块化,减少代码重复,提高代码质量。 五、数据访问集成 Spring提供了对各种数据库访问技术的支持,如JDBC、Hibernate、MyBatis等。在“holaspring”项目中,...
- **BeanFactory与ApplicationContext:** Spring提供了两个核心接口——BeanFactory和ApplicationContext,前者是最基础的工厂接口,后者提供了更丰富的应用上下文环境。 **2. Spring的IoC容器** - **Bean的生命...
- **数据访问抽象**:Spring提供了一种通用的数据访问抽象层,包括高效且易于使用的JDBC框架,极大地提高了数据库操作的效率并减少了潜在的错误。此外,Spring的数据访问框架还集成了Hibernate等其他对象关系映射...
封装可以提高代码的复用性,例如创建一个BaseController,提供通用的方法如结果集返回、参数校验等,其他Controller可以继承这个基类,减少重复代码。 3. **异常处理**:SpringBoot提供了全局异常处理机制,可以...
1. **减少代码开发量**:框架能够通过一系列预定义的功能模块和通用的设计模式,减少开发者编写重复代码的工作量。 2. **注重流程处理**:框架提供了一套标准化的操作流程,帮助开发者遵循最佳实践,从而提高软件的...
这样既可以利用`List`接口提供的通用方法,又可以利用`ArrayList`的具体实现细节。 #### 4. MVC 模式中控制器的作用 **题目**: MVC模式中,控制器的作用是? - **选项**: - A: 从模型中获取数据并指定这些数据...
这些数据类型为各种应用场景提供了基础,例如,使用字符串存储用户信息,哈希存储对象,列表实现消息队列,集合存储不重复元素,有序集合则可用于排行榜等需求。 2. **持久化机制**:Redis提供了两种主要的持久化...