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层,由于扫描粒度大
导致内部一些问题所以失效