Spring中的AOP

1、前置增强

继承与MethodBeforeAdvice,并实现before方法,用于在目标类方法前执行。

在配置文件中:

<bean id="a" class="继承于MethodBeforeAdvice接口的类"/>
       <bean id="b" class="原始类"/>
       <bean id="c" class="org.springframework.aop.framework.ProxyFactoryBean">
              p:proxyInterfaces="代理的接口,即原始类的接口"
              p:interceptorNames="a"//指定使用的增强
              p:target-ref="b"//被代理的类
              p:其它属性
       </bean>

2、后置增强

继承于AfterReturningAdvice,并实现afterReturning方法,用于在目标类方法调用后执行。

3、环绕增强

继承于MethodInterceptor,并实现invoke方法,综合了前两者。

4、异常抛出增强

最适合用在事务中,异常时回滚

继承于ThrowsAdvice,必须实现方法afterThrowing(...)

5、引介增强

类 extends DelegatingIntroductionInterceptor implements 新增的接口,并实现接口中的方法。它是一种类级别的增强。

前面介绍的增强用于织入到方法的前面,后面等信息,而切点进一步描述织入到哪些类的哪些方法上

6、静态普通方法名匹配切面

默认匹配所有类及方法,所以一般情况下需要自己改写。类extends StaticMethodMatcherPointcutAdvisor,重写matches(Method method, Class clazz)方法,可以匹配指定的方法名。通过改写getClassFilter方法,可以使得匹配规则限定某些类。
7、静态正则表达式方法匹配切面

8、动态切面

类 extends DynamicMethodMatcherPointcut,重写matches(Method method, Class clazz, Object[] args)方法。再在spring中进行动态切面的配置就装配好了。

9、流程切面

由某一个方法发起对其它方法的调用都织入增强,就可以使用流程切面来完成。

10、复合切点切面

如果希望由某一个方法发起对特定一个方法的增强时

11、引介切面

12、自动创建代理

上面的切面配置比较麻烦,spring提供了简单的配置方法
(1)基于Bean配置名规则的自动代理创建器,BeanNameAutoProxyCreator
(2)基于Advisor匹配机制的自动代理创建器,DefaultAdvisorAutoProxyCreator
(3)基于AspjectJ注解标签的自动代理创建器,AnnotationAwareAspectJAutoProxyCreator
下面介绍更为简单的配置AOP的方法(基于@AspectJ和schema)
使用@AspectJ需要JDK5.0以上,spring的asm模块,aspectj.weaver,aspectj.tools类包
13、基于AspectJ的简单例子
@Aspect
public class PreGreetingAspect{
    @Before("execution(* greetTo(..))")
    public void beforeGreeting(){
        System.out.println("How are you");
    }
}
这样就表示执行任何greetTo方法时织入前置增强,然后进行spring的配置:
 <beans>
        <aop:aspectj-autoproxy proxy-target-class="true"/>//true表示用CGLib动态代理技术
        <bean id="waiter" class="com.xxx.NaiveWaiter"/>//目标类
        <bean class="PreGreetingAspect的全限定名"/>
    </beans>
(1)execution:执行目标类方法
execution(public * *To(..)):以To为后缀的public方法
execution(* com.xxx.Waiter.*(..)):匹配Waiter接口的所有方法
execution(* com.xxx.Waiter+.*(..)):匹配Waiter接口及其实现类中的所有方法
execution(* com.xxx.*(..)):xxx包下的所有类的所有方法
execution(* com.xxx..*(..)):xxx包,子孙包下的所有类的所有方法
execution(* com..*.*Dao.find*(..)):前缀为com的任何包下后缀为Dao的方法,且方法前缀为find
execution(* joke(String, ..)):*表示任何类型,..表示任意类型且参数个数不限
即.* 表示包下所有类,..*表示包及子孙包下所有类
(2)@annotation:所有指定注解的目标类方法
(3)args:方法接受一个类名
args(com.xxx.Waiter):匹配运行时入参时Waiter类型(包含子类)的方法,等价于args(com.xxx.Waiter+),也等价于execution(* *(com.xxx.Waiter+))
(4)@args:方法接受一个类名且必须接受一个注解类的类名
(5)within:最小粒度是类
(6)target
(7)@within
(8)@target
(9)this
。。。

且以上方法的入参支持的通配符不同

除@AspectJ注解的方式之外,其它还有<aop:advisor>方式(如引用第三方包中的增强和切点),<aop:aspect>方式等

14、逻辑运算符
与:&&的转义符(&amp;&amp;)或者 使用and
或:|| 或者 or
非:! 或者 not,当not位于表达式开头时,开头必须加一个空格
15、增强类型
@Before
@AfterReturning
@Around
@AfterThrowing
@After
@DeclareParents
16、命名切点
public class TestNamePointcut{
        @Pointcut("within(com.xxx.*)")
        private void inPackage(){}  //private表示只能在本类中引用,inPackage()是切点名称
        
        @Pointcut("execution(* greetTo(..))")
        protected void greetTo(){}
        
        @Pointcut("inPackage() and greetTo()") //此处引用inPackage()和greetTo()的命名切点,并设为public
        public void inPkgGreetTo(){}
    }
public class TestAspect{
        @Before("TestNamePointcut.inPkgGreetTo()")//引用其它类中的public切点
        public void pkgGreetTo(){
           //todo ...
        }
    }

17、增强织入的顺序

18、以上args(),this()等都是通过指定类名来匹配的,还可以通过匹配参数名

@Before(args(name, num, ..))
public void func(int num, String name)  //这里就通过name和num参数名称相当于args(String, int)

19、AOP代理中的proxy-target-class 参数

如果你希望在不改变代码的情况 下代理目标对象的所有方法,而不只是实现自接口的方法(强制使用CGLIB代理),见http://www.xuebuyuan.com/993356.html

20、JDK&CGLib代理

JDK基于接口的动态代理要求方法必须是public的,且static由于是类级别的,public static接口也是不行的,public final则可以

CGLib通过扩展被增强类,动态创建其子类的方式实现动态代理,所以private,static,final修饰的方法都不行



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值