- 浏览: 100517 次
- 性别:
- 来自: 武汉
最新评论
-
zljerityzljerity:
<#assign ipage=page?number&g ...
freeMark全解 -
qiankai86:
...
freeMark全解
Spring 在进行反射时候主要有两种策略,一种是直接用 JDK 的反射,另外是用 CgLib 。 cglib是一个开源项目, 是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO字节码的动态生成。cglib项目主页: http://cglib.sourceforge.net/ CgLib 底层用的 asm Asm 是一个强大的 Java 字节码生成框架,和 BCEL 或者 SERP 很类似,但是小很多,可以动态修改 java 字节码 . 其中最核心的代码为 newProxyInstance (obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), InvocationHandler invocationHandler); 从 obj.getClass().getInterfaces() 可以看出,如果直接用 JDK 的反射需要创建接口,接口是用来搞架构的,但是对于非常非常小的项目去写接口有点麻烦。 而 CgLib 就可以不用接口,它底层调用 asm 动态生成一个代理类去覆盖父类中非 final 的方法,然后实现 MethodInterceptor 接口的 intercept 方法,这样以后直接调用重写的方法,比 JDK 要快。 但是加载 cglib 消耗时间比直接 jdk 反射时间长,开发的过程中,如果是反复动态生成新的代理类推荐用 jdk 自身的反射,反之用 cglib. Spring 在 Bean 工厂中有一个方法 public void setOptimize (boolean optimize)- 是否使用 CGLIB 代理优化策略 . 仅用于 CGLIB 下面是一个 demo( HelloWorld ) Jar 包 : cglib-2.2.jar, asm-all-3.1 Helloworld 方法 package com.greysh.cglib; /** * @author Genix.Cao */ public class HelloWorld { public void say() { System.out.println("Hello World"); } } 代理类 package com.greysh.cglib; /** * @author Genix.Cao */ import java.lang.reflect.Method; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("Before Helloworld~"); methodProxy.invokeSuper(object, args); System.out.println("After Helloworld~"); return null; } } 测试类 package com.greysh.cglib; /** * @author Genix.Cao */ import net.sf.cglib.proxy.Enhancer; public class TestCglib { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(HelloWorld.class); enhancer.setCallback(new CglibProxy()); HelloWorld helloWorld = (HelloWorld) enhancer.create(); helloWorld.say(); } } Cglib 使用起来学习路线还是很低的 原理是实现 MethodInterceptor 这个接口 System.out.println("Before Helloworld~"); methodProxy.invokeSuper(object, args); System.out.println("After Helloworld~"); 这里就是 AOP 的思想 然后去装载的时候先要生成一个 Enhancer 类 这个类的作用是先设定被代理类 enhancer.setSuperclass(HelloWorld.class); 然后实例化代理类 enhancer.setCallback(new CglibProxy()); HelloWorld helloWorld = (HelloWorld) enhancer.create(); 这样被调用的类就是被 asm 动态改变改变后的类 Spring proxy 有趣问题:
测试代码 上面这种情况下程序可以正常运行,但是如果UserDAOImpl实现了一个接口,其他不变 这种情况下,程序将不能正常运行,会抛出java.lang.ClassCastException异常 理解上面这种情况产生的原因需要了解Spring AOP的实现原理。
advisedSupport.isOptimize()与advisedSupport.isProxyTargetClass()默认返回都是false,所以在默认情况下目标对象有没有实现接口决定着Spring采取的策略,当然可以设置advisedSupport.isOptimize()或者advisedSupport.isProxyTargetClass()返回为true,这样无论目标对象有没有实现接口Spring都会选择使用CGLIB代理。所以在默认情况下,如果一个目标对象如果实现了接口Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象,可以通俗的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出j ava.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现任何接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类。 以上说的是默认情况下,也可以手动配置一些选项使Spring采用CGLIB代理。 org.springframework.transaction.interceptor.TransactionProxyFactoryBean是org.springframework.aop.framework. ProxyConfig的子类,所以可以参照ProxyConfig里的一些设置如下所示,将optimize和proxyTargetClass任意一个设置为true都可以强制Spring采用CGLIB代理。
使用CGLIB代理也就不会出现前面提到的ClassCastException问题了, 也可以在性能上有所提高,但是也有它的弊端,Spring doc原文解释如下optimization will usually mean that advice changes won't take effect after a proxy has been created. For this reason, optimization is disabled by default。
代理 ; 对于 JDK 动态代理 ( 缺省代理 ) 无效 .
public class UserDAOImpl{
public void save() {
// TODO Auto-generated method stub
System.out.println("user saved");
}
}
//相关配置,省略了一些不相关内容
<bean id="userDAO" class="UserDAOImpl">
<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target">
<ref local="userDAO" />
</property>
</bean>
ApplicationContext ctx =
new FileSystemXmlApplicationContext("applicationContext.xml");
UserDAOImpl userDAOImpl =
(UserDAOImpl)ctx.getBean("userDAOProxy");
userDAOImpl.save();
public class UserDAOImpl implements UserDAO {
public void save() {
// TODO Auto-generated method stub
System.out.println("user saved");
}
}
Spring 实现AOP是依赖JDK动态代理和CGLIB代理实现的。
以下是JDK动态代理和CGLIB代理简单介绍
JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。
Spring是依靠什么来判断采用哪种代理策略来生成AOP代理呢?以下代码就是Spring的判断逻辑
//org.springframework.aop.framework.DefaultAopProxyFactory
//参数AdvisedSupport 是Spring AOP配置相关类
public AopProxy createAopProxy(AdvisedSupport advisedSupport)
throws AopConfigException {
//在此判断使用JDK动态代理还是CGLIB代理
if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass()
|| hasNoUserSuppliedProxyInterfaces(advisedSupport)) {
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. "
+ "Add CGLIB to the class path or specify proxy interfaces.");
}
return CglibProxyFactory.createCglibProxy(advisedSupport);
} else {
return new JdkDynamicAopProxy(advisedSupport);
}
}
//相关配置,省略了一些不相关内容
<bean id="userDAO" class="UserDAOImpl">
<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target">
<ref local="userDAO" />
</property>
<property name="optimize">
<value>true</value>
</property>
<property name="proxyTargetClass">
<value>true</value>
</property>
</bean>
发表评论
-
ofbiz 之entity实体
2014-03-25 18:16 939ofbiz 之entity实体 1. 实体定义文件 实体定 ... -
ofbiz迷你语言
2012-08-08 17:13 2298simple-map-processor 和 sim ... -
ofbiz之entity 实体解析
2012-08-08 17:12 1507ofbiz 之entity实体 1. 实体定义文件 实体定 ... -
ofbiz之旅-实体简介(中英译)
2012-08-09 09:34 1167OFBIZ ENTITY ENGINE COOKBOOK = ... -
OFBIz之旅[结构]
2012-08-08 17:03 1483OFBIz之旅[结构] 注意: 1,持久层,在OFBI ... -
java concurrent 探秘(2)
2011-08-08 14:21 913java concurrent 探秘(2) Blo ... -
java concurrent 探秘
2011-08-08 11:02 821java concurrent 探秘 我们都知道,在JD ... -
one-to-one 一对一主键关联映射_单向
2011-08-03 17:22 1311one-to-one 一对一主键关联映射_单向 一对一主键关 ... -
JavaScript验证正则表达式大全
2011-07-27 17:18 915上篇文章《JavaScript验证正则表达式大全》说的是jav ... -
JavaScript验证正则表达式大全
2011-07-27 17:17 827JavaScript验证正则表达式大全 JavaScript验 ... -
js 收集1
2011-01-14 09:49 10551.javascript的数组API Js代码 ... -
struts 核心解析
2010-12-03 14:25 2444一、概述 Struts2的核心是一个Fil ... -
Java类库中的集合类解析
2010-11-29 16:05 1086这篇我准备从源码的高度来看看集合中各个实现类的是如何组织我们存 ... -
jboss classloader机制以及scope配置
2010-11-29 15:06 17131. 概念介绍 UCL : org.jboss.mx. ... -
总结和对比一下(jboss,tomcat,jetty)容器的classloader机制
2010-11-29 14:58 1976总结和对比一下(jboss,tomcat,je ... -
jboss,tomcat,jetty 容器的classloader机制
2010-11-29 14:53 4573背景 前段时间一直在做应用容器的迁移,将公司的应用 ... -
Session,Cookie,jsessionid和Url重写
2010-11-29 12:55 1929Session,Cookie,jsessionid ... -
DWR work
2010-11-25 18:14 888这段时间较闲,研究了一 ... -
CXF jaxws spring configuration
2010-11-19 16:27 1593最近在cxf-zh中有人问及了有关Spring配置CXF Cl ... -
线程安全总结2
2010-11-17 16:48 816站内很多人都问我,所谓线程的“工作内存”到底是个什么东西? ...
相关推荐
Spring AOP支持不同的代理策略,包括JDK动态代理和CGLIB代理。如果被代理的类没有实现接口,Spring AOP会采用CGLIB来生成代理对象。CGLIB(Code Generation Library)是一个开源的代码生成库,它允许运行时在内存中...
Spring常见面试题 Spring框架是Java平台上的一个开源的软件框架,由Rod Johnson创建,現在由Spring.io维护。Spring框架提供了一个通用的编程模型和配置机制,...有两种使用方式,一种是xml的方式,一种是注解的方式。
1. **JDK动态代理**:Spring在没有CGLIB库的情况下,会使用Java的反射API创建动态代理。动态代理类会实现目标接口,并在调用接口方法时插入通知。因此,使用JDK动态代理的目标类必须实现至少一个接口。 2. **CGLIB...
AOP通过代理模式实现,Spring 提供了基于注解和XML配置两种方式来定义切面。 总之,Spring + SpringMVC + Mybatis 的组合是企业级Java应用中常见的技术栈,它们共同提供了强大的框架支持,帮助开发者构建高效、可...
2. **多数据源支持**:不同数据源可能有不同的分页实现,通过反射,我们可以针对每个数据源编写对应的分页策略,并在运行时根据数据源类型选择合适的策略。 3. **插件化设计**:使用反射,我们可以设计一个插件化的...
本章将介绍一些策略,使你的bean能够在生命周期的各个阶段接收到Spring容器的通知。你可以通过实现Spring定义的特定接口,通过反射指定Spring可以调用的方法,或者使用JSR-250的JavaBeans生命周期注解来实现这一点。...
在Spring中,AOP是通过动态代理实现的,有两种主要的代理方式:JDK动态代理和CGLIB代理。前者针对实现了接口的类,后者则针对未实现接口的类。源码中,`Advisor`、`Pointcut`、`Aspect`等接口及其实现类定义了切面的...
【Spring 依赖注入详解】 在 Spring 框架中,依赖注入(Dependency Injection,简称 DI)是一种关键的设计模式,它允许我们解耦...结合使用两种注入策略,可以更好地管理对象的依赖关系,提高代码的可读性和可维护性。
本文介绍了两种在 Spring MVC 应用中防御 XSS 和 SQL 注入攻击的方法:数据入库前非法字符转义与显示时非法字符转义,并提供了相应的示例代码。此外,还提到了利用框架内置工具来简化这一过程的可能性。这些方法不仅...
Spring AOP提供了两种动态代理技术: 1. **JDK代理**:如果目标对象实现了接口,Spring会使用Java的动态代理机制,通过反射创建一个代理对象,该代理对象在调用目标对象的方法时会执行通知逻辑。 2. **CGLIB代理**...
这两种技术的结合使得开发者能够更好地管理和控制数据库操作,同时保持代码的简洁和模块化。下面我们将详细探讨如何配置Hibernate与Spring进行集成,以及它们各自的作用。 首先,Hibernate是一个对象关系映射(ORM...
"spring与springmvc常见面试题" ...答:有两种方式:1、编程式事务,在代码中硬编码。(不推荐使用)2、声明式事务,在配置文件中配置(推荐使用)声明式事务又分为两种:基于注解的声明式事务和基于 XML 的声明式事务。
Spring提供了两种动态代理的方式:JDK动态代理和CGLIB代理。 1. JDK动态代理: JDK动态代理基于Java的反射机制,适用于目标对象实现了接口的情况。在Java.lang.reflect包下,有两个关键类:InvocationHandler和...
总的来说,实现一个类似Spring的IoC注解装配系统是一项复杂但有益的任务,它需要对Java反射、注解处理以及设计模式有深入的理解。这样的系统可以帮助我们构建松耦合、易于测试的代码,提高开发效率。在实际开发中,...
在IT行业中,Spring框架是Java开发中的一个核心组件,它主要负责管理对象的生命周期和对象间的依赖关系。本文将深入探讨Spring框架的核心特性——依赖注入(Dependency Injection, DI)和面向切面编程(Aspect-...
例如,Spring的注解解析器会在容器启动时,查找所有的bean,并根据Resource注解来注入依赖,这个过程中涉及到类型匹配和名称匹配两种策略。 通过以上的详细解释,我们理解了Spring框架中IoC容器的运行机制、依赖...
4. **适配器模式与代理模式**:这两种设计模式在Spring中被广泛应用于实现AOP等功能。 5. **Spring MVC核心概念**: - **核心类和接口**:了解Spring MVC中的关键组件,如`DispatcherServlet`、`HandlerMapping`等...
在Java中,主要有两种动态代理技术: - **JDK动态代理**:基于接口实现的动态代理。使用`java.lang.reflect.Proxy`类和`InvocationHandler`接口实现。 - **CGLIB动态代理**:基于子类继承的动态代理。适用于没有...