在配置Shiro与Spring框架的时候,用到了Shiro的注解方式实现权限,做一下记录方便以后查看
applicationContext-shiro.xml 中关于注解AOP的配置
<!--
Enable Shiro Annotations for Spring-configured beans. Only run after
-->
<!-- the lifecycleBeanProcessor has run: -->
<!--<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true"></property>
</bean>
<bean id="authorizationAttributeSourceAdvisor"
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
其中
DefaultAdvisorAutoProxyCreator是Spring的默认AOP Creator, 属于一种AOP代理Creator
而AuthorizationAttributeSourceAdvisor是shiro框架定义的Advisor
Advisor属于Spring定义的概念,包括Advice与PointCut,对于该Shiro的Advisor,其中Advice用来代理实现Shiro的权限植入
通过查看AuthorizationAttributeSourceAdvisor的代码,发现其PointCut就是处理Shiro定义的各种注解
private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
new Class[] {
RequiresPermissions.class, RequiresRoles.class,
RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class}
这样就很清楚了,该Advisor就是用于处理包括以上注解的类的代理功能
再看除开Shiro框架的Spring配置applicationContext.xml中关于事务的配置,按照标准的数据库事务配置方式
<aop:config>
<aop:advisor pointcut="execution(* Service.*ServiceX.*(..))" advice-ref="txAdvice" />
</aop:config>
从这次开发Shiro开始,重新理解了以上配置的具体概念,关于advisor的配置跟上面解释的一样,一个advisor包括一个pointcut和advice
事务AOP使用了表达式的pointCut和事务的advice为txAdvice
那么这个aop:config 会根据AOP的namespace处理方式,由AopNamespaceHandler负责创建AspectJAwareAdvisorAutoProxyCreator这样一个AOP的Creator
特别关键是一定要记住这里的config配置与内部的advisor配置是没有关系的,不能理解为该config只对内部事务的advisor生效,这个理解是错的
这两个配置完全是独立的,真正的意义是配置了一个AOP的Creator和一个事务的切面,两者是没有包含关系
再来说一下AOP的Creator的机制,Creator会实现BeanPostProcessor接口,在Spring初始化bean完成后(Action是在调用的时候初始化,因为是scope=prototype)
在单个bean初始化,假设为A, 所有在Spring容器中存在的Creator都会对bean A进行代理检测,如果在Spring配置的Advisor(包括Advice和PointCut)中的PointCut能满足
Bean A的方法(包括表达式写法和注解写法,主要由对应的Advisor实现匹配算法),则会使用对应的Advice进行切面代理
那么如果有多个Creator,假设为Creator_A 和 Creator_B , 则会对上述初始化完成的Bean A进行两次代理过程。如果有N个Creator,则会代理N次。
对每个Creator均可配置代理方式,当配置proxyTargetClass=true代表cglib方式进行代理,如果是proxyTargetClass=false则代表使用jdk动态代理
在实际开发中应该避免出现多次重复代理,当配置多个Creator的代理方式不同的情况下,因为cglib无法继续代理jdk动态代理过的代理对象,项目环境初始化会出现问题
而且这也是没有必要的,出现多次重复代理是属于开发中对Spring的AOP机制不熟悉造成的
最后再重点记录一下:
<aop:config>
<aop:advisor pointcut="execution(* Service.*ServiceX.*(..))" advice-ref="txAdvice" />
</aop:config>
上述配置配置了一个AspectJAwareAdvisorAutoProxyCreator,通过aop:config通过AopNamespaceHandle进行处理
配置了一个advisor,该advisor包括配置好的pointcut和advice
重点: 两个配置是没有关系的,是两个配置,一个是AOP的Creator, 一个是AOP的Advisor