Spring的Bean,AOP以及工具类初探
1.Bean(Ioc)
BeanWrapper
根据JavaDoc中的说明,BeanWrapper提供了设置和获取属性值(单个的或者是批量的),获取属性描述信息、查询只读或者可写属性等功能。不仅如此,BeanWrapper还支持嵌套属性,你可以不受嵌套深度限制对子属性的值进行设置。Spring 从核心而言,是一个DI 容器,其设计哲学是提供一种无侵入式的高扩展性框架。即无需代 码中涉及Spring专有类,即可将其纳入Spring容器进行管理。 作为对比,EJB则是一种高度侵入性的框架规范,它制定了众多的接口和编码规范,要求实现者必须 遵从。侵入性的后果就是,一旦系统基于侵入性框架设计开发,那么之后任何脱离这个框架的企图都将付 出极大的代价。 为了避免这种情况,实现无侵入性的目标。Spring 大量引入了Java 的Reflection机制,通过动态 调用的方式避免硬编码方式的约束,并在此基础上建立了其核心组件BeanFactory,以此作为其依赖注入 机制的实现基础。 org.springframework.beans包中包括了这些核心组件的实现类,核心中的核心为BeanWrapper 和BeanFactory类。
BeanWrapper示例
public class Company {
@Setter @Getter
private String name;
@Setter @Getter
private Employee manager;
}
public class Employee {
@Setter @Getter
private String name;
@Setter @Getter
private float salary;
}
BeanWrapper companyWrapper = new BeanWrapperImpl(new Company());
companyWrapper.setPropertyValue("name","alibaba-inc...");
PropertyValue cname = new PropertyValue("name","taobao....");
companyWrapper.setPropertyValue(cname);
BeanWrapper employWrapper = new BeanWrapperImpl(new Employee());
employWrapper.setPropertyValue("name","chuanqing");
companyWrapper.setPropertyValue("manager",employWrapper.getWrappedInstance());
Float salary = (Float) companyWrapper.getPropertyValue("manager.salary");
String name = (String)companyWrapper.getPropertyValue("manager.name");
System.out.println(name);
BeanFactory
类图结构
- BeanFactory作为一个主接口不继承任何接口,暂且称为一级接口。
- 有3个子接口继承了它,进行功能上的增强。这3个子接口称为二级接口。
- ConfigurableBeanFactory可以被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry
- ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,无所不包,称为四级接口。(这4级接口是BeanFactory的基本接口体系。继续,下面是继承关系的2个抽象类和2个实现类:)
- AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分功能。
- AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额外实现了二级接口AutowireCapableBeanFactory
- DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最强大的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。
- 最后是最强大的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些功能,使自己更强大。
InitializingBean
- spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用。
- Spring的加载bean的源码类(AbstractAutowireCapableBeanFactory)。
- spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用
- 实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖
- 如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。
CustomEditorConfigurer,PropertyEditorRegistrar,PropertyEditorSupport
特殊的bean factory后置处理器,通过CustomEditor绑定Registrar,为指定Bean 执行自定义的绑定(比如动态代理)。
PropertyEditorRegistrar示例
public class HSFSpringProviderBeanRegistrar implements
PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
if(!(registry instanceof BeanWrapperImpl)) {
return ;
}
BeanWrapperImpl beanWrapper = (BeanWrapperImpl) registry;
Class<?> clazz = null;
try {
clazz = Class.forName("com.taobao.hsf.app.spring.util.HSFSpringProviderBean", true, registry.getClass().getClassLoader());
} catch (Throwable e) {
RecordLog.info("cannot find class for com.taobao.hsf.app.spring.util.HSFSpringProviderBean", e);
}
if(null == clazz
|| null == beanWrapper.getWrappedClass()
|| !clazz.isAssignableFrom(beanWrapper.getWrappedClass())) {
return ;
}
registry.registerCustomEditor(Object.class, "target", new HSFSpringProviderBeanTargetEditor());
}
}
HSFSpringProviderBeanTargetEditor示例
public class HSFSpringProviderBeanTargetEditor extends PropertyEditorSupport {
@Override
public void setValue(Object value) {
if(value != null && needProxy(value)) {
try {
Class<?>[] classes = MethodUtil.getAllInterfaces(value.getClass());
InvocationHandler invocationHandler = new HsfProviderInvocationHandler(value);
Object object = Proxy.newProxyInstance(value.getClass().getClassLoader(), classes, invocationHandler);
super.setValue(object);
RecordLog.info("success to proxy hsf provider bean typed: " + value.toString());
return ;
} catch (Exception e) {
RecordLog.info(e.getClass().getName(), e);
}
super.setValue(value);
}
super.setValue(value);
}
/***
* 需要注意多次代理
* @param value
* @return
*/
private boolean needProxy(Object value) {
if (Proxy.isProxyClass(value.getClass())) {
InvocationHandler invocationHandler = Proxy.getInvocationHandler(value);
if (!(invocationHandler instanceof HsfProviderInvocationHandler)) {
return true;
} else {
return false;
}
} else {
return true;
}
}
}
2.AOP
一、AOP 概念
- Joinpoint:它定义在哪里加入你的逻辑功能,对于Spring AOP,Jointpoint指的就是Method。
- Advice:特定的Jointpoint处运行的代码,对于Spring AOP 来讲,有Before advice、AfterreturningAdvice、ThrowAdvice、AroundAdvice(MethodInteceptor)等。
- Pointcut:一组Joinpoint,就是说一个Advice可能在多个地方织入,
- Aspect:这个我一直迷惑,它实际是Advice和Pointcut的组合,但是Spring AOP 中的Advisor也是这样一个东西,但是Spring中为什么叫Advisor而不叫做Aspect。
- Weaving:将Aspect加入到程序代码的过程,对于Spring AOP,由ProxyFactory或者ProxyFactoryBean负责织入动作。
- Target:这个很容易理解,就是需要Aspect功能的对象。
- Introduction:引入,就是向对象中加入新的属性或方法,一般是一个实例一个引用对象。当然如果不引入属性或者引入的属性做了线程安全性处理或者只读属性,则一个Class一个引用也是可以的(自己理解)。Per-class lifecycle or per-instance life cycle
二、AOP 种类
- 静态织入:指在编译时期就织入Aspect代码,AspectJ好像是这样做的。
- 动态织入:在运行时期织入,Spring AOP属于动态织入,动态织入又分静动两种,静则指织入过程只在第一次调用时执行;动则指根据代码动态运行的中间状态来决定如何操作,每次调用Target的时候都执行(性能较差)。
三、Spring AOP 代理原理
Spring AOP 是使用代理来完成的,Spring 会使用下面两种方式的其中一种来创建代理
- JDK动态代理,特点只能代理接口,性能相对较差,需要设定一组代理接口。
- CGLIB 代理,可代理接口和类(final method除外),性能较高(生成字节码)。
四、Spring AOP 通知类型
- BeforeAdvice:前置通知需实现MethodBeforeAdvice,但是该接口的Parent是BeforeAdvice,致于什么用处我想可能是扩展性需求的设计吧。或者Spring未来也并不局限于Method的JoinPoint(胡乱猜测)。BeforeAdvice可以修改目标的参数,也可以通过抛出异常来阻止目标运行。
- AfterreturningAdvice:实现AfterreturningAdvice,我们无法修改方法的返回值,但是可以通过抛出异常阻止方法运行。
- AroundAdvice:Spring 通过实现MethodInterceptor(aopalliance)来实现包围通知,最大特点是可以修改返回值,当然它在方法前后都加入了自己的逻辑代码,因此功能异常强大。通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用)。
- ThrowsAdvice:通过实现若干afterThrowing()来实现。
- IntroductionInterceptor:Spring 的默认实现为DelegatingIntroductionInterceptor
五、Spring AOP Pointcut
以上只是Advice,如果不指定切入点,Spring 则使用所有可能的Jointpoint进行织入(当然如果你在Advice中进行方法检查除外)。因此切入点在AOP中扮演一个十分重要的角色。Spring 2.0 推荐使用AspectJ的Annocation的切入点表达式来定义切入点,或者使用aop:xxx/来定义AOP,这方面本篇不做考虑。
- Pointcut:它是Spring AOP Pointcut的核心,定义了getClassFilter()和getMethodMatcher()两个方法。
- ClassFilter:定义了matches(Class cls)一个方法。
- MethodMatcher() 定义了matches(Method,Class),isRuntime(),matches(Mathod,Class,Object[])三个方法,如果isRuntime()返回true则表示为动态代理(实际是动态代理的动态代理),则调用第三个方法(每访问一次调用一次),否则调用第一个方法(并且只调用一次)
Spring AOP 静态切入点的几个实现。
- ComposablePointcut 太复杂一个切入点无法表达就用这个,union MethodMatcher和ClassFilter或者intersection MethodMatcher、ClassFilter和Pointcut。为什么不实现union Pointcut? 而只能通过Pointcuts类对Pointcut进行union操作。
- ControlFlowPointcut 想对程序的运行过程进行追踪就用这个
- DynamicMatchMatcherPointcut 想用动态AOP 就用这个
- JdkRegexpMethodPointcut 想使用正则表达式就用这个
- Perl5RegexpMethodPointcut
- NameMatchMethodPointcut 想用方法名字来匹配就用这个
- StaticMethodMatcherPointcut 静态切入点就用这个
没有人反对你直接实现Pointcut。
六、Spring AOP 中的Advisor其实就是Aspect
PointcutAdvisor:
其实一般使用DefaultPointcutAdvisor就足够了,给它Advice和Pointcut。 当然如果想少写那么几行代码也可以使用NameMatchMethodPointcutAdvisor,RegexpMethodPointcutAdvisor等。 更多Advisor可以查看API文档。IntroductionAdvisor:
默认实现为DefaultIntroductionAdvisor。
七、AOP ProxyFactory
使用代码实现AOP 可使用ProxyFactory
声明式AOP 可使用ProxyFactoryBean
ProxyFactoryBean 需要设定 target,interceptorNames(可以是Advice或者Advisor,注意顺序)
对接口代理需设置proxyInterfaces
3.工具包
内置的resouce类型
- UrlResource
- ClassPathResource
- FileSystemResource
- ServletContextResource
- InputStreamResource
- ByteArrayResource
- EncodedResource 也就是Resource加上encoding, 可以认为是有编码的资源
- VfsResource(在jboss里经常用到, 相应还有 工具类 VfsUtils)
- org.springframework.util.xml.ResourceUtils 用于处理表达资源字符串前缀描述资源的工具. 如: "classpath:".
- 有 getURL, getFile, isFileURL, isJarURL, extractJarFileURL
工具类
- org.springframework.core.annotation.AnnotationUtils 处理注解
- org.springframework.core.io.support.PathMatchingResourcePatternResolver 用 于处理 ant 匹配风格(com/.jsp, com/**/.jsp),找出所有的资源, 结合上面的resource的概念一起使用,对于遍历文件很有用. 具体请详细查看javadoc
- org.springframework.core.io.support.PropertiesLoaderUtils 加载Properties资源工具类,和Resource结合
- org.springframework.core.BridgeMethodResolver 桥接方法分析器. 关于桥接方法请参考: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.4.5
- org.springframework.core.GenericTypeResolver 范型分析器, 在用于对范型方法, 参数分析.
- org.springframework.core.NestedExceptionUtils
xml工具
- org.springframework.util.xml.AbstractStaxContentHandler
- org.springframework.util.xml.AbstractStaxXMLReader
- org.springframework.util.xml.AbstractXMLReader
- org.springframework.util.xml.AbstractXMLStreamReader
- org.springframework.util.xml.DomUtils
- org.springframework.util.xml.SimpleNamespaceContext
- org.springframework.util.xml.SimpleSaxErrorHandler
- org.springframework.util.xml.SimpleTransformErrorListener
- org.springframework.util.xml.StaxUtils
- org.springframework.util.xml.TransformerUtils
其它工具集
- org.springframework.util.xml.AntPathMatcherant风格的处理
- org.springframework.util.xml.AntPathStringMatcher
- org.springframework.util.xml.Assert断言,在我们的参数判断时应该经常用
- org.springframework.util.xml.CachingMapDecorator
- org.springframework.util.xml.ClassUtils用于Class的处理
- org.springframework.util.xml.CollectionUtils用于处理集合的工具
- org.springframework.util.xml.CommonsLogWriter
- org.springframework.util.xml.CompositeIterator
- org.springframework.util.xml.ConcurrencyThrottleSupport
- org.springframework.util.xml.CustomizableThreadCreator
- org.springframework.util.xml.DefaultPropertiesPersister
- org.springframework.util.xml.DigestUtils摘要处理, 这里有用于md5处理信息的
- org.springframework.util.xml.FileCopyUtils文件的拷贝处理, 结合Resource的概念一起来处理, 真的是很方便
- org.springframework.util.xml.FileSystemUtils
- org.springframework.util.xml.LinkedCaseInsensitiveMap
- key值不区分大小写的LinkedMap
- org.springframework.util.xml.LinkedMultiValueMap一个key可以存放多个值的LinkedMap
- org.springframework.util.xml.Log4jConfigurer一个log4j的启动加载指定配制文件的工具类
- org.springframework.util.xml.NumberUtils处理数字的工具类, 有parseNumber 可以把字符串处理成我们指定的数字格式, 还支持format格式, convertNumberToTargetClass 可以实现Number类型的转化.
- org.springframework.util.xml.ObjectUtils有很多处理null object的方法. 如nullSafeHashCode, nullSafeEquals, isArray, containsElement, addObjectToArray, 等有用的方法
- org.springframework.util.xml.PatternMatchUtilsspring里用于处理简单的匹配. 如 Spring's typical "xxx", "xxx" and "xxx" pattern styles
- org.springframework.util.xml.PropertyPlaceholderHelper用于处理占位符的替换
- org.springframework.util.xml.ReflectionUtils反映常用工具方法. 有 findField, setField, getField, findMethod, invokeMethod等有用的方法
- org.springframework.util.xml.SerializationUtils用于java的序列化与反序列化. serialize与deserialize方法
- org.springframework.util.xml.StopWatch一个很好的用于记录执行时间的工具类, 且可以用于任务分阶段的测试时间. 最后支持一个很好看的打印格式. 这个类应该经常用
- org.springframework.util.xml.StringUtils
- org.springframework.util.xml.SystemPropertyUtils
- org.springframework.util.xml.TypeUtils用于类型相容的判断. isAssignable
- org.springframework.util.xml.WeakReferenceMonitor弱引用的监控
和web相关的工具
- org.springframework.web.util.CookieGenerator
- org.springframework.web.util.HtmlCharacterEntityDecoder
- org.springframework.web.util.HtmlCharacterEntityReferences
- org.springframework.web.util.HtmlUtils
- org.springframework.web.util.HttpUrlTemplate 这个类用于用字符串模板构建url, 它会自动处理url里的汉字及其它相关的编码. 在读取别人提供的url资源时, 应该经常用
- String url = "http://localhost/myapp/{name}/{id}"
- org.springframework.web.util.JavaScriptUtils
- org.springframework.web.util.Log4jConfigListener 用listener的方式来配制log4j在web环境下的初始化
- org.springframework.web.util.UriTemplate
- org.springframework.web.util.UriUtils处理uri里特殊字符的编码
- org.springframework.web.util.WebUtils
- org.springframework.web.util.
为什么引入spring-beans.dtd相对路径文件
maybe 减少网络传输
Spring的Bean,AOP以及工具类初探的更多相关文章
- 获取Spring容器中Bean实例的工具类(Java泛型方法实现)
在使用Spring做IoC容器的时候,有的类不方便直接注入bean,需要手动获得一个类型的bean. 因此,实现一个获得bean实例的工具类,就很有必要. 以前,写了一个根据bean的名称和类型获取b ...
- 高可用的Spring FTP上传下载工具类(已解决上传过程常见问题)
前言 最近在项目中需要和ftp服务器进行交互,在网上找了一下关于ftp上传下载的工具类,大致有两种. 第一种是单例模式的类. 第二种是另外定义一个Service,直接通过Service来实现ftp的上 ...
- spring boot 结合Redis 实现工具类
自己整理了 spring boot 结合 Redis 的工具类引入依赖 <dependency> <groupId>org.springframework.boot</g ...
- SSM(Spring)中,在工具类中调用服务层的方法
因为平时在调用service层时都是在controller中,有配置扫描注入,spring会根据配置自动注入所依赖的服务层. 但因我们写的工具类不属于controller层,所以当所写接口需要调用服务 ...
- spring -mvc service层调用工具类配置
在service层时调用工具类时服务返回工具类对象为空 在此工具类上加上@Component注解就可以了 @Component:把普通pojo实例化到spring容器中,相当于配置文件中的 <b ...
- 项目ITP(四) javaweb http json 交互 in action (服务端 spring 手机端 提供各种工具类)勿喷!
前言 系列文章:[传送门] 洗了个澡,准备写篇博客.然后看书了.时间 3 7 分.我慢慢规律生活,向目标靠近. 很喜欢珍惜时间像叮当猫一样 正文 慢慢地,二维码实现签到将要落幕了.下篇文章出二维码实 ...
- spring mvc 文件上传工具类
虽然文件上传在框架中,已经不是什么困难的事情了,但自己还是开发了一个文件上传工具类,是基于springmvc文件上传的. 工具类只需要传入需要的两个参数,就可以上传到任何想要上传的路径: 参数1:Ht ...
- Spring中可以复用的工具类&特性记录
Spring 里有用工具类: GenericTypeResolver 解析泛型类型.核心逻辑还是调用 ResolvableTypeResolvableType 解析泛型类型 BeanWrapper 利 ...
- spring boot 文件上传工具类(bug 已修改)
以前的文件上传都是之前前辈写的,现在自己来写一个,大家可以看看,有什么问题可以在评论中提出来. 写的这个文件上传是在spring boot 2.0中测试的,测试了,可以正常上传,下面贴代码 第一步:引 ...
随机推荐
- java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))
Java提高篇--对象克隆(复制)(转自:http://www.cnblogs.com/Qian123/p/5710533.html#_label0) 阅读目录 为什么要克隆? 如何实现克隆 浅克 ...
- 手机浏览器wap网页点击链接触发颜色区块的问题解决办法
引子 在做HTML5 WAP网页的时候,一行内容做了2个链接,点击一个标签的时候,整个颜色块会闪一下,影响美观.需求针对这种情况来问我,能否把这个一闪的颜色去掉.我当时就想,这个怎么去?那我也不好直接 ...
- HDU 5130 Signal Interference(计算几何 + 模板)
HDU 5130 Signal Interference(计算几何 + 模板) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5130 Descripti ...
- jquery学习笔记3——jq HTML
jQuery最常用的部分就是操作DOM,jQuery提供了一系列操作DOM的相关方法,使其很容易: 一.获取 1.获取内容 text()方法 设置或返回所选元素的文本内容: html()方法 ...
- java 枚举类型和数据二进制等问题思考
.以下代码的输出结果是什么? int X=100; int Y=200; System.out.println("X+Y="+X+Y); System.out.println(X+ ...
- jqGrid使用整理
jqGrid使用整理 jqGrid是一款处理表格展现的jQuery插件,支持分页.滚动加载.搜索.锁定.拖动等一系列对表格的常规操作.以下是最近项目中实践jqGrid的整理 1.引入到项目中来 jqG ...
- python 元组 字符串 字典 列表嵌套练习题1
最近学习做的习题,直接复制过来 缩进就乱掉了,所以直接以图片方式上传,题目和答案一起
- Javaweb 第12天 JSP、EL技术
第12天 JSP.EL技术 今日任务: JSP技术入门和常用指令 JSP的内置对象&标签介绍 EL表达式&EL的内置对象 课堂笔记 1.JSP技术入门和常用指令 1.1.JSP的由来. ...
- Python操作IHTMLDocument2用于自动化测试
有些软件的界面采用Win32窗口嵌套一个IE控件,用Spy++只能识别出一个Internet Explorer_Server控件.常用的几个API函数无法取到IE控件里面的内容,更无法对里面的控件进行 ...
- php 导出 Excel 报错 exception 'PHPExcel_Calculation_Exception' with message
exception 'PHPExcel_Calculation_Exception' with message '粉丝数据!C2679 -> Formula Error: Operator '= ...