jdk,cglib代理

jpa注解需要cglib代理????????????????

annotation-driven 中的proxy-target-class是注入方式(针对一个bean来讲,是jdk形式对应的接口注入,还是cglib的子类注入)

aspectj-autoproxy 生成切面bean的方式,(针对生产的代理对象用jdk方式,还是cglib方式)

对于生产代理对象来讲都可,除非目标对象有接口,否则只能用cglib的注入,(cglib用来继承类或实现接口以产生对象。)使用cglib要加jar包

用jdk代理目标对象要有接口

用cglib目标对象不能为final

 

 

代理于事务:

因为我们使用事务基于service,service是代理生成的所以,代理的方式和事务配置的起作用的代理方式要一致,否则也会导致事务无效,要么遵循标签写在实现类方法上

 

http://sishuok.com/forum/blogPost/list/3845.html

 

<tx:annotation-driven transaction-manager="transactionManager" 

                                       proxy-target-class="true"/>注入方式(cglib)

<!-- 启用@AspectJ风格的切面声明 --> <aop:aspectj-autoproxy proxy-target-class="true"/>,spring切面生成代理方式

 

 

 

而Spring的@Transactional背后,则是使用SpringAOP来对我们的UserDao进行了代理。代理的方式有2种,jdk代理或者cglib代理。

如UserDao的实例是我们要代理的对象,暂且称作target

jdk代理针对那些实现了相应的接口的类,创建出的代理对象也是实现了同样的接口,同时该代理对象包含一个target

cglib代理针对类都可以进行代理,创建出的代理对象是继承了target类,同时该代理对象内部包含一个target(既可以是接口,也可以是直接的类(无接口的类))

注意:proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,

那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。

 

@Transactional放到接口上 基于JDK动态代理也是可以工作的。

基于JDK动态代理 ,可以将@Transactional放置在接口和具体类上。(方法)

基于CGLIB类代理,只能将@Transactional放置在具体类上。(方法)

 

因此 在实际开发时全部将@Transactional放到具体类上,而不是接口上。(方法)

 

 

 

代理于spring data 

 

spring jpa搭建遇到的问题如果使用的代理不是cglib,会导致运行报错,

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.jasig.cas.services.DefaultServicesManagerImpl]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class org.jasig.cas.services.DefaultServicesManagerImpl

at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:212)

at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)

at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:447)

 

<aop:aspectj-autoproxy/>

<tx:annotation-driven transaction-manager="transactionManager"/>

上面这一套不行,用的是jdk

下面这套可以:

 

 

 

代理于注入方式:

 

jdk代理:

把实现类注入给接口,否则注入不成功,比如在shrio权限动态加载中写的注意

cglib代理,被注入的类不需要接口,即可注入

 

 

代理于缓存

spring cache 是基于aop代理的缓存,当我们配置的缓存是jdk那么他可放在接口也可放在实现类,当定义的是cglib的话只能的定义在接口,

当我们的dao(mapper)的实现是代理产产生的那么应该是应jdk,此时可以配置在service(实现类,接口上)(mapper实现类,接口上)@Cacheable

但是如果<context:component-scan base-package="com.esteel.web" />扫描的是粗粒度的所有包(不仅仅是controller),那么 @Cacheable 放到service层无效

,有时@Transactional事务也会失效,这是都只能放到dao(mapper)接口层(因为其实现类直接由代理生成的,生成时即织入成jvm 运行时bean),如果是放在service层,由于扫描粒度大

导致内部一些问题所以失效

 

猜你喜欢

转载自yuhuiblog6338999322098842.iteye.com/blog/2314821