日期:2014-05-17  浏览次数:21207 次

Spring Ioc管理AspectJ切面与运行时织入(LWT)应用方式实现容器内外切面一体化

???? Spring的AOP功能对于大部分的应用来说可以说是足够的,但这种AOP还是有不少情况下满足不了需求,而且Spring的AOP是通过其自身的代理实现的,如果因为某些原因不能或不想使用代理,例如ORM情况下的实体,一般由JPA、Hibernate,topLink等持久化框架创建的,并不在Spring容器的管理下,那就只好另想办法了。

????

???? AspectJ可以说是目前开源面向切面编程最强的实现,几乎能满足所有切面编程的需求,能管理任何你想管理的bean,并且能和Spring完美的整合在一起,那么有了能大小通吃的AspectJ,你还想用Spring自己的阉割过的AOP鸟炮么。

?

?????? 管理容器内的切面大家一般都会用了,不会用的就看Spring文档的AOP部分。但管理容器外的切面,那就非得AspectJ亲自出面了,再进一步,如果能让 AspectJ 的容器外 切面也能享受 Spring Ioc 的待遇,那么Spring容器内外就能真正打成一片了,如此就能发挥无穷威力,做更多以前难以做到的事情。比如Entity的字段级授权控制。那就是小菜一碟了。

?

???? 说了那么多虚的,下面给例子大家看看,就知道威力何在了(本例子需要给eclipse安装AJDT插件用来编译 切面类,也可以通过 iajc的 ant任务编译AspectJ切面类):

?

?? 1.定义一些常用命名切点

package com.yotexs.aop;
import org.aspectj.lang.annotation.Pointcut;
/**
 * 命名切点类,定义一些基本的切点匹配模式,可以在任何其他的AspectJ切面定义中引用
 * <p>
 * 用法:如匹配classpath中注解了@Repository的类的所有public的方法
 * <pre>
 * &#064;Around(&quot;com.yotexs.aop.Pointcuts.publicMethodOnly() &amp;&amp; com.yotexs.aop.Pointcuts.atRepository()&quot;)
 * </pre>
 * @author bencmai 麦田枭鹰 QQ:36767935 
 */
public abstract class Pointcuts {
    /** 匹配public方法 */
    @Pointcut("execution(public * *.*(..))")
    public void publicMethodOnly() {}
    /** 匹配public get方法 */
    @Pointcut("execution(public * *.get*(..))")   
    public void publicGetMethodOnly() {}
    /** 匹配@Repository注解过的类 */
    @Pointcut("@within(org.springframework.stereotype.Repository)")
    public void atRepository() {}
    /** 匹配@Service注解过的类 */
    @Pointcut("@within(org.springframework.stereotype.Service)")
    public void atService() {}
    /** 匹配@Configurable注解过的类 */
    @Pointcut("@within(org.springframework.beans.factory.annotation.Configurable)")
    public void atConfigurable() {}    
}

?

?2.以注解方式定义一个AspectJ(如果你喜欢用AspectJ语言,也可以用AspectJ语言编码方式定义切面)

package com.yotexs.aop.spring;

import com.yotexs.ext.springsecurity.aspectj.AspectJCallback;
import com.yotexs.ext.springsecurity.aspectj.AspectJSecurityInterceptor;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;

/**
 * Spring AspectJ 方式服切面配置
 * 
 * @author bencmai 麦田枭鹰 QQ:36767935 
 */
//@Component
@Aspect
public class SecurityAspectJ implements Ordered {
    protected final Logger             logger = LoggerFactory.getLogger(getClass());
    private int                               order  = 1;       //用于指定切面类之间的增强织入顺序
    
    //注入Spring Security AspectJ方法安全拦截器处理器,此拦截器来自Spring容器内,
      //但可以同时用于容器内外的所有需要方法调用的安全监控和事后返回数据过滤的审查(不知道什么原因,网上还没有发现有文章介绍Spring Security 这种比MethodSecurityInterceptor强悍的多的用法)
    @Autowired
    private AspectJSecurityInterceptor securityInterceptor;
    
    /** 服务层命名切点--匹配注解了@Service的服务层暴露的public方法 */
    @Pointcut("com.yotexs.aop.Pointcuts.publicMethodOnly()&& com.yotexs.aop.Pointcuts.atService()")
    public void atServiceLayer() {}
    /** 持久层命名切点--匹配注解了@Repository的持久层暴露的public方法 */
    @Pointcut("com.yotexs.aop.Pointcuts.publicMethodOnly()&& com.yotexs.aop.Pointcuts.atRepository()")
    public void atDaoLayer() {}
    /** 领域层命名切点--匹配注解了@Configurable的持久层暴露的public get方法 */
    @Pointcut("com.yotexs.aop.Pointcuts.publicGetMethodOnly()&& com.yotexs.aop.Pointcuts.atConfigurable()")
    public void atEntityLayer() {}

    /** 环绕增强容器内服务层--做服务调用安全和事后数据过滤检查。用于保护方法方法级 */
    @Around("atServiceLayer()")
    public Object atServiceLayerDoMethodSecurityCheck(final ProceedingJoinPoint joinPoint) throws Throwable {
        final AspectJCallback callback = new AspectJCallback() {//回调封装
            public Object proceedWithObject() throws Throwable {