Cglib动态代理是如何实现的动态代理

博客分类:
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Trasactional注解的事务管理,但在通过基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务是有区别的,我们接下来看看到底有哪些区别。
一、基础工作
首先修改我们上一次做的 ,如下所示:
将xml声明式事务删除
java代码:
&aop:config expose-proxy="true"&
&!-- 只对业务逻辑层实施事务 --&
&aop:pointcut id="txPointcut" expression="execution(* cn.javass..service..*.*(..))" /&
&aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/&
&/aop:config&
并添加注解式事务支持:
java代码:
&tx:annotation-driven transaction-manager="txManager"/&
在我们的BaseService接口上添加 @Transactional 使该方法开启事务
java代码:
package cn.javass.common.
public interface IBaseService&M extends java.io.Serializable, PK extends java.io.Serializable& {
@Transactional
//开启默认事务
public int countAll();
在我们的log4j.properties中添加如下配置,表示输出spring的所有debug信息
java代码:
log4j.logger.org.springframework=INFO,CONSOLE
在我们的resources.properties里将hibernate.show_sql=true 改为true,为了看到hibernate的sql。
单元测试类:
java代码:
package cn.javass.ssonline.spider.service.
import org.junit.T
import org.junit.runner.RunW
import org.springframework.beans.factory.annotation.A
import org.springframework.test.context.ContextC
import org.springframework.test.context.junit4.SpringJUnit4ClassR
import org.springframework.test.context.transaction.TransactionC
import cn.javass.demo.service.UserS
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-config.xml"})
public class UserServiceTest2 {
@Autowired
private UserService userS
public void testCreate() {
userService.countAll();
基础工作做好,接下来我们详细看看 Spring基于 JDK动态代理 和 CGLIB类级别代理到底有什么区别。
二、基于JDK动态代理:
java代码:
&tx:annotation-driven transaction-manager="txManager"/&
该配置方式默认就是JDK动态代理方式
运行单元测试,核心日志如下:
java代码:
09:58:44 [main] DEBUG org.springframework.orm.hibernate4.HibernateTransactionManager - Creating new transaction with name [cn.javass.common.service.impl.BaseService.countAll]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
//开启事务
09:58:44 [main] DEBUG org.springframework.orm.hibernate4.HibernateTransactionManager - Opened new Session
09:58:44 [main] DEBUG org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.orm.hibernate4.SessionHolder@1184a4f] for key [org.hibernate.internal.SessionFactoryImpl@107b56e] to thread [main] //绑定session到ThreadLocal
09:58:44 [main] DEBUG org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization
09:58:44 [main] DEBUG org.springframework.transaction.interceptor.TransactionInterceptor - Getting transaction for [cn.javass.common.service.impl.BaseService.countAll]
09:58:44 [main] DEBUG org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.hibernate4.SessionHolder@1184a4f] for key [org.hibernate.internal.SessionFactoryImpl@107b56e] bound to thread [main]
09:58:44 [main] DEBUG org.springframework.orm.hibernate4.HibernateTransactionManager - Found thread-bound Session
09:58:44 [main] DEBUG org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.hibernate4.SessionHolder@1184a4f] for key [org.hibernate.internal.SessionFactoryImpl@107b56e] bound to thread [main]
Hibernate:
count(*) as col_0_0_
tbl_user usermodel0_
09:58:44 [main] DEBUG org.springframework.orm.hibernate4.HibernateTransactionManager - Committing Hibernate transaction on Session
//提交事务
09:58:44 [main] DEBUG org.springframework.transaction.support.TransactionSynchronizationManager - Removed value [org.springframework.orm.hibernate4.SessionHolder@1184a4f] for key [org.hibernate.internal.SessionFactoryImpl@107b56e] from thread [main] //解除绑定session到ThreadLocal
到此我们可以看到事务起作用了,也就是说即使把@Transactional放到接口上 基于JDK动态代理也是可以工作的。
三、基于CGLIB类代理:
java代码:
&tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/&
该配置方式是基于CGLIB类代理
启动测试会报错,No Session found for current thread,说明事务没有起作用
java代码:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1024)
at cn.javass.common.dao.hibernate4.BaseHibernateDao.getSession(BaseHibernateDao.java:63)
at cn.javass.common.dao.hibernate4.BaseHibernateDao.aggregate(BaseHibernateDao.java:238)
at cn.javass.common.dao.hibernate4.BaseHibernateDao.countAll(BaseHibernateDao.java:114)
at cn.javass.common.service.impl.BaseService.countAll(BaseService.java:60)
at cn.javass.common.service.impl.BaseService$$FastClassByCGLIB$$5b04dd69.invoke(&generated&)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:618)
at cn.javass.demo.service.impl.UserServiceImpl$$EnhancerByCGLIB$$7d46c567.countAll(&generated&)
at cn.javass.ssonline.spider.service.impl.UserServiceTest2.testCreate(UserServiceTest2.java:20)
如果将注解放在具体类上或具体类的实现方法上才会起作用。
java代码:
package cn.javass.common.service.
public abstract class BaseService&M extends java.io.Serializable, PK extends java.io.Serializable& implements IBaseService&M, PK& {
@Transactional()
//放在抽象类上
public int countAll() {
return baseDao.countAll();
运行测试类,将发现成功了,因为我们的UserService继承该方法,但如果UserService覆盖该方法,如下所示,也将无法织入事务(报错):
java代码:
package cn.javass.demo.service.
public class UserServiceImpl extends BaseService&UserModel, Integer& implements UserService {
//没有@Transactional
public int countAll() {
return baseDao.countAll();
四、基于aspectj的
java代码:
&tx:annotation-driven transaction-manager="txManager" mode="aspectj" proxy-target-class="true"/&
在此就不演示了,我们主要分析基于JDK动态代理和CGLIB类代理两种的区别。
五、结论:
基于JDK动态代理 ,可以将@Transactional放置在接口和具体类上。
基于CGLIB类代理,只能将@Transactional放置在具体类上。
因此 在实际开发时全部将@Transactional放到具体类上,而不是接口上。
JDK动态代理
1.1、Spring使用JdkDynamicAopProxy实现代理:
java代码:
package org.springframework.aop.
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
//注意此处的method 一定是接口上的method(因此放置在接口上的@Transactional是可以发现的)
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
注意此处的method 一定是接口上的method(因此放置在接口上的@Transactional是可以发现的)
1.2、如果&tx:annotation-driven 中 proxy-target-class="true" ,Spring将使用CGLIB动态代理,而内部通过Cglib2AopProxy实现代理,而内部通过DynamicAdvisedInterceptor进行拦截:
java代码:
package org.springframework.aop.
final class Cglib2AopProxy implements AopProxy, Serializable {
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
//注意此处的method 一定是具体类上的method(因此只用放置在具体类上的@Transactional是可以发现的)
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
1.3、Spring使用AnnotationTransactionAttributeSource通过查找一个类或方法是否有@Transactional注解事务来返回TransactionAttribute(表示开启事务):
java代码:
package org.springframework.transaction.
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource implements Serializable {
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
if (attr != null) {
而AnnotationTransactionAttributeSource又使用SpringTransactionAnnotationParser来解析是否有@Transactional注解:
java代码:
package org.springframework.transaction.
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
Transactional ann = AnnotationUtils.getAnnotation(ae, Transactional.class);
if (ann != null) {
return parseTransactionAnnotation(ann);
public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
此处使用AnnotationUtils.getAnnotation(ae, Transactional.class); 这个方法只能发现当前方法/类上的注解,不能发现父类的注解。 Spring还提供了一个 AnnotationUtils.findAnnotation()方法 可以发现父类/父接口中的注解(但spring没有使用该接口)。
如果Spring此处换成AnnotationUtils.findAnnotation(),将可以发现父类/父接口中的注解。
这里还一个问题,描述如下:
在接口中删除@Transactional
//开启默认事务
java代码:
package cn.javass.common.
public interface IBaseService&M extends java.io.Serializable, PK extends java.io.Serializable& {
public int countAll();
在具体类中添加@Transactional
java代码:
package cn.javass.common.service.
public abstract class BaseService&M extends java.io.Serializable, PK extends java.io.Serializable& implements IBaseService&M, PK& {
@Transactional()
//开启默认事务
public int countAll() {
return baseDao.countAll();
我们之前说过,基于JDK动态代理时, method 一定是接口上的method(因此放置在接口上的@Transactional是可以发现的),但现在我们放在具体类上,那么Spring是如何发现的呢??
还记得发现TransactionAttribute是通过AnnotationTransactionAttributeSource吗?具体看步骤1.3:
而AnnotationTransactionAttributeSource 继承AbstractFallbackTransactionAttributeSource
java代码:
package org.springframework.transaction.
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
public TransactionAttribute getTransactionAttribute(Method method, Class&?& targetClass) {
//第一次 会委托给computeTransactionAttribute
//计算TransactionAttribute的
private TransactionAttribute computeTransactionAttribute(Method method, Class&?& targetClass) {
// Ignore CGLIB subclasses - introspect the actual user class.
Class&?& userClass = ClassUtils.getUserClass(targetClass);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
//①此处将查找当前类覆盖的方法
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// First try is the method in the target class.
TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
if (txAtt != null) {
return txA
//找类上边的注解
// Second try is the transaction attribute on the target class.
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAtt != null) {
return txA
//②如果子类覆盖的方法没有 再直接找当前传过来的
if (specificMethod != method) {
// Fallback is to look at the original method.
txAtt = findTransactionAttribute(method);
if (txAtt != null) {
return txA
// Last fallback is the class of the original method.
return findTransactionAttribute(method.getDeclaringClass());
//①此处将查找子类覆盖的方法
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// ClassUtils.getMostSpecificMethod
public static Method getMostSpecificMethod(Method method, Class&?& targetClass) {
Method specificMethod = null;
if (method != null && isOverridable(method, targetClass) &&
targetClass != null && !targetClass.equals(method.getDeclaringClass())) {
specificMethod = ReflectionUtils.findMethod(targetClass, method.getName(), method.getParameterTypes());
} catch (AccessControlException ex) {
// security settings are disallowi leave
// 'specificMethod' null and fall back to 'method' below
return (specificMethod != null ? specificMethod : method);
可以看出将找到当前类的那个方法。因此我们放置在BaseService countAll方法上的@Transactional起作用了。
//②如果子类覆盖的方法没有 再直接找当前传过来的
if (specificMethod != method) {
// Fallback is to look at the original method.
txAtt = findTransactionAttribute(method);
if (txAtt != null) {
return txA
// Last fallback is the class of the original method.
return findTransactionAttribute(method.getDeclaringClass());
查找子类失败时直接使用传过来的方法。
因此,建议大家使用基于Schema风格的事务(不用考虑这么多问题,也不用考虑是类还是方法)。而@Transactional建议放置到具体类上,不要放置到接口。
作者原创【】
浏览 37320
开涛兄,使用JDK动态代理,注解@Transactional在具体子类上,当子类有自定义方法时,context.getbean便会出现以下异常,何故? Exception in thread "main" org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'testDao' must be of type [com.test.dao.TestDao], but was actually of type [com.sun.proxy.$Proxy13] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:376) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:979) at test.Test.main(Test.java:12)了解了,JDK代理是动态创建实现接口的子类,CGLIB是针对子类的扩展。所以上面会出现cast问题。
如雷贯耳 谢谢
佩服 这两个的区别都研究得这么透彻核心就是 aop时&& JDK动态代理 CGLIB类代理 的区别不?对 是的
jinnianshilongnian
浏览量:1977808
浏览量:2505606
浏览量:5153660
浏览量:199212
浏览量:1415313
浏览量:208853
浏览量:4723936
浏览量:560008
浏览量:613412
No realms have been configured! ...
Spring源码一步步分析——客户端请求流转Spring MV ...
现在新推出了一个权限框架,叫jCasbin(https://g ...
抛出异常@ExceptionHandler({Unauthor ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'您还可以使用以下方式登录
当前位置:&>&&>&&>& > 设计模式--动态代理(CGLIB)
设计模式--动态代理(CGLIB)
&上一篇文章《设计模式--动态代理(JDK)》已经写了JDK中动态代理的应用,这篇文章将介绍动态代理在CGLIB中应用。,从上篇文章中我们知道使用JDK动态代理是有一定限制。就是被代理类必须至少实现一个接口,因为JDK为我们生成的动态代理也是实现这个接口的。所以如果没有接口,JDK基本就歇菜了。CGLIB正好弥补了JDK的这个缺陷,他的被代理类是无需实现接口,因为它的实现机制是继承被代理类,从而创建一个代理对象(继承被代理对象)的。CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。将它的jar包引入到我们的程序就可以使用了。需要注意的是CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。所以cglib包中必须包含asm,否则会报错可以选择其他的CGLIB版本,比如cglib-nodep,它里面就含有asm包。在网上看了好多例子都说CGLIB运用了回调,虽然知道他们讲了什么,但是不明白为什么调用代理的方法就直接跳转到AuthProxy中的intercept方法中。网上总是说当调用代理对象的方法的时候,会自动调用intercept方法,但是WHY,就算把生成的代理反编译了,迷迷糊糊看不懂啊。然后化整为零从回调方法开始一个个击破,最后画出了相同的类图。现在对CGLIB的回调才稍微明白点了。&下面写一个例子,也是在网上看到的,但是个人感觉很不错,在这里和大家分享。&1 代理类对表的各类操作&package com.tgb.cglibTpublic class TableDao {public void create(){
System.out.println(create() is running...);
public void delete(){
System.out.println(delete() is running...);
public void update(){
System.out.println(update() is running...);
public void query(){
System.out.println(query() is running...);
}}&&2生成代理类&package com.tgb.cglibTimport net.sf.cglib.proxy.Epublic class TableDAOFactory {private static TableDao tDao = new TableDao();
public static TableDao getInstance(){
public static TableDao getAuthInstance(AuthProxy authProxy){
Enhancer en = new Enhancer();
//Enhancer用来生成一个原有类的子类(代理类)
//进行代理
en.setSuperclass(TableDao.class);
//设置织入逻辑
en.setCallback(authProxy); //注册回调函数
//生成代理实例
return (TableDao)en.create();
} }&Enhancer是CGLIB的核心包,它是生成代理类的工具。在生成代理类的同时根据我们的参数对代理类进行设置,比如setSuperclass方法就是调用Enhancer的方法让生成的代理对象继承TabbleDao(被代理类)。setCallback就是设置回调。最后create方法,生成最后的代理类。如果想查看的生成的代理可以根据4中客户端中代码&System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,F:\class);&获取,通过反编译工具jd-gui,可以查看生成的代理类。&3 定义拦截类package com.tgb.cglibTimport java.lang.reflect.Mimport net.sf.cglib.proxy.MethodIimport net.sf.cglib.proxy.MethodPpublic class AuthProxy implements MethodInterceptor {private String userN
AuthProxy(String userName){
this.userName = userN
//实现MethodInterceptor接口的intercept方法
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
//权限判断
if(!张三.equals(userName)){
System.out.println(你没有权限!);
return arg3.invokeSuper(arg0, arg2);//把方法封装成了一个对象,然后回调父类(代理类中对应的方法)
}}在用CGLIB生成的代理类中,当调用代理类中的方法时,会调用intercept方法。因为在生成的代理类中(create、delete、update、query)的方法都会调用intercept,在intercept方法我们就可以增加我们想要添加的各种操作。最后的invokeSuper使用反射机制回调父类相应的方法。4 客户端调用&package com.tgb.cglibTimport net.sf.cglib.core.DebuggingClassWpublic class Client { public static void main(String[] args) { //将新生成的所有类存放到F:class,为了看生成的代理类,用反编译工具编译后可以看具体生成的代理类
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,F:\class);
haveAuth();
//haveNoAuth();
//执行代理的增删改查
public static void doMethod(TableDao dao){
dao.create();
dao.query();
dao.update();
dao.delete();
//模拟有权限
public static void haveAuth(){
TableDao tDao = TableDAOFactory.getAuthInstance(new AuthProxy(张三));
doMethod(tDao);
//模拟无权限
public static void haveNoAuth(){
TableDao tDao = TableDAOFactory.getAuthInstance(new AuthProxy(李四));
doMethod(tDao);
}&&5 总结:(1)CGLIB的使用网上虽然有很多,但是却没有说为什么要这样写。所以看源码是很有必要的,但是哎。(2)问题较多无法解决的时候,需要从简单处入手,各个击破。&就爱阅读www.92to.com网友整理上传,为您提供最全的知识大全,期待您的分享,转载请注明出处。
欢迎转载:
推荐:    博客分类:
原创声明:本博客来源与本人另一博客【】原创作品,绝非他处摘取
代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
动态代理实现主要有2种形式,主要分为: 1.jdk动态代理:
1)原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理,位于java.lang.reflect包下)
2)实现方式:
1. 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
2. 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3. 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4. 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
2~4步骤可合并
package proxy.
import java.lang.reflect.InvocationH
import java.lang.reflect.M
import java.lang.reflect.P
import org.junit.T
public class JDKProxy{
private Object targetO//代理目标
public Object CustomerProxy(Object obj) {
targetObject =
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(),new targetHandler());
class targetHandler
implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务...");
Object returnValue = method.invoke(targetObject, args);//回调被代理目标的方法userDaoImpl.add();
System.out.println("提交事务");
return returnV
public static void main(String[] args) {
JDKProxy jdkProxy = new JDKProxy();
Customer userDao = (Customer)jdkProxy.CustomerProxy(new CustomerImpl());
userDao.shopping();
public void test1(){
Customer customer = new CustomerImpl();
Customer cus = (Customer) Proxy.newProxyInstance(customer.getClass().getClassLoader(), customer.getClass().getInterfaces(),new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
return method.invoke(proxy, args);
cus.shopping();
3)不足点:jdk动态代理,必须是面向接口,目标业务类必须实现接口 2.CGLIB代理
1.原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
2.实现方法:
package proxy.
import java.lang.reflect.M
import org.junit.T
import net.sf.cglib.proxy.E
import net.sf.cglib.proxy.MethodI
import net.sf.cglib.proxy.MethodP
import proxy.model.C
public class CGLIBProxy {
private Object targetO
private Object createProxy(Object obj){
targetObject =
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());//设置代理对象,父类,说明是继承,所有代理对象不能为final
enhancer.setCallback(new MyHandler());
return enhancer.create();//创建代理
class MyHandler implements MethodInterceptor{
public Object intercept(Object arg0, Method method, Object[] args,
MethodProxy arg3) throws Throwable {
System.out.println("开启事务..");
Object returnValue = method.invoke(targetObject, args);
System.out.println("提交事务....");
return returnV
void test1() {
CGLIBProxy cglibProxy = new CGLIBProxy();
Customer customer = (Customer)cglibProxy.createProxy(new Customer());
customer.eat();
public void test2(){
Customer customer = new Customer();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(customer.getClass());
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy arg3) throws Throwable {
if(method.getName().equals("eat")){
System.out.println("customer的eat方法被拦截了。。。。");
Object invoke = method.invoke(proxy, args);
System.out.println("真实方法拦截之后。。。。");
return method.invoke(proxy, args);
Customer cus = (Customer) enhancer.create();
cus.eat();
3.注意点:被代理目标不是是final修饰的类(final修饰类不能被继承) spring aop代理原理
1.注意点:
如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
如果目标对象实现了接口,可以强制使用CGLIB实现AOP
如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
2.强制把jdk代理转换成cglib代理
添加CGLIB库,SPRING_HOME/cglib/*.jar
在spring配置文件中加入&aop:aspectj-autoproxy proxy-target-class = "true" /&
传统AOP有默认的实现代理机制,可不需要专门指定代理,如自定义代理对象,可在类生成的时候自动代理,自动代理的方式主要有2种,一种是基于Bean名称的自动代理BeanNameAutoProxyCreator,另外一种是基于切面信息的自动代理DefaultAdvisorAutoProxyCreatorspring mvc 使用DefaultAdvisorAutoProxyCreator实现自动代理 配置
&!--定义一个表示声明使用自动代理的类
&bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/&
&!-- 定义代理类 --&
&bean id="exceptionHandler" class="com.kaizhi.platform.util.ExceptionHandler"/&
&!-- 定义支持正则表达式的通知 --&
&bean id="exceptionHandlerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&
&property name="advice"&
&ref bean="exceptionHandler"/&
&/property&
&property name="patterns"&
&value&.save*.*&/value&//正则匹配需要拦截的方法
&/property&
spring mvc 使用BeanNameAutoProxyCreator自动代理配
&!-- 基于BeanNameAutoProxyCreator,Bean名称的自动代理 --&
&!-- 定义代理类 --&
&bean id="exceptionHandler" class="com.kaizhi.platform.util.ExceptionHandler"/&
&bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"&
&!-- 拦截的业务bean --&
&property name="beanNames" value="*adminFinanceService"/&
&!-- 拦截的通知 --&
&property name="interceptorNames" value="exceptionHandler"/&
浏览: 22249 次
来自: 广州
浏览量:14093
分享一款代码生成器,拖拽式组件结合流式处理,很容易的访问数据库 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 动态代理实现原理 的文章

 

随机推荐