Spring之AOP

AOP应用:日志、安全、声明式事务、缓存等

Spring的aop基于动态代理,只能实现方法拦截,要实现字段拦截和构造器拦截,可使用AspectJ或者JBoss。

以下是几个需要掌握的概念:

通知:通知定义了切面是什么什么时候应用。分为前置后置等等。

连接点:应用执行过程中能够插入切面的一个点

切点:定义了切面在何处应用。

切面:通知+切点

引入:允许我们向现有类添加方法或属性。

织入:把切面应用到目标对象并创建新的代理对象的过程。

个人理解:比如一个工厂会产生垃圾,而工厂只负责生产,垃圾希望由切面执行,连接点是可能(但不一定)产生垃圾,并希望切面作用的点,而切点是产生了垃圾并需要切面作用的点,通知即我希望什么时候切面去处理切点处的垃圾以及如何处理,织入即把切面覆盖在目标对象的切点方法上面,一旦调用目标对象的这些符合切点的方法,目标对象的代理对象将会拦截调用,然后执行通知方法,再转发调用给目标对象。引入是通过引入新的接口为对象添加方法等。

编译期织入:AspectJ

类加载期织入:AspectJ 5支持

运行期织入:Spring aop

Spring AOP的AspectJ切点,Spring仅支持AspectJ切点指示器的一个子集,其中只有execution()指示器是执行匹配,其他都是用来限制匹配的。

在一个类上使用@Aspect注解即可使该类成为一个切面(AspectJ 5),切面包含通知及切点,例如:

@Aspect // 这个注解使此类成为切面
public class a_Aspect {
    // 切点
    @Pointcut("execution(* chapter4.Domain.*(..))")
    public void perform() {
    }

    // 通知
    @Before("perform()")
    public void before() {
        System.out.println("前置通知");
    }

    @After("perform()")
    public void after() {
        System.out.println("后置通知");
    }


    @Around("perform()")
    public void around(ProceedingJoinPoint pjp) {
        try {
            before();
            pjp.proceed();
            after();
        } catch (Throwable e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

这里重点是环绕通知,如果要在前置通知和后置通知间共享信息,那么得有一个新的成员变量传递信息,环绕通知在内部实现了信息共享。

要使切面类发挥作用,还需要配置类的一个注解,如下:

@Configuration
@ComponentScan
@EnableAspectJAutoProxy//启动自动代理,切面类才能发挥作用
//对应xml为<aop:aspectj-autoproxy>
public class Config {
    @Bean
public a_Aspect getAspect() {
    return new a_Aspect();
}
}

想为目标bean添加方法,则要新建一个接口NewMethod和其实现类DefaultNewMethod,重点是这一步:

//新建一个切面类,为目标添加方法
@Aspect
public class NewMethod_Aspect {
    //value:哪种类型的bean要引入该接口,加号表示此类的子类也行
    //defaultImpl:使用该接口的哪个实现类
    @DeclareParents(value="chapter4.Domain+",defaultImpl=DefaultNewMethod.class )
public NewMethod nm;
}

对应xml配置为:

<!-- 匹配接口interfaceA的bean会在父类中实现interfaceB接口-->
<aop:declare-parents types-matching="interfaceA+" implement-interface="interfaceB" default-impl="interfaceB_Imp"/>
<!-- 也可以这样,但是interfaceB_Imp这个bean要自己装配-->

<aop:declare-parents types-matching="interfaceA+" implement-interface="interfaceB"delegate-ref="interfaceB_Imp"/>
</aop:aspect>

测试类里:为Domain类添加一个新方法g()

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class TestDemo {
    @Autowired
    private Domain d;

    @Test
    public void test() {
        d.fun();
        NewMethod nm = (NewMethod) d;
        nm.g();
    }
}

如果你需要声明切面,但是又不能为通知类添加注解的时候,那么就必须转向XML配置了。

Spring的AOP功能不及AspectJ,所以我们有必要使用AJDT插件开发,插件网站:http://www.eclipse.org/ajdt/downloads/

语法及具体使用我也不知道了。。。

最后,如果通知方法有参数,我们希望传入切点方法的参数也传给通知方法:

<aop:pointcut expression="execution(* chapter4.*(int))and args(count)" id="pc"/>




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值