SpringAOP配置


AOP与SpringAOP

AOP(Aspect Oriented Programming),面向切面编程,通过预编译和动态代理实现的一种技术。也是Spring框架的一部分利用AOP可以对业务逻辑的各个部分进行隔离,各部分业务逻辑明确耦合性降低,提高程序的可重用性,同时这也是动态代理的好处。
AOP是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许定义纵向的关系,但并不适合定义横向的关系。

在这里插入图片描述


SpringAOP的要素
横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
通知(Advice):执行增强的方法,也就是对目标方法拦截后所作的处理
目标(Target):被通知对象
代理(Proxy):目标对象应用通知后的对象
切面(Aspect):通常是一个类,里面可以定义通知及通知的方式
切入点(Pointcut):没必要区分与JointPoint(连接点),拦截这个词相当恰当,定义为切入点的方法在执行过程中会被拦截,执行增强。


环境搭建

导入依赖aop

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>

配置文件添加约束

 xmlns:aop="http://www.springframework.org/schema/aop"

 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd

自定义类的实现

以用户业务逻辑为例
用户业务逻辑接口

public interface UserService {
    public void create();

    public void delete();

    public void retrieve();

    public void update();
}

用户业务逻辑实现(目标对象)

public class UserServiceImp implements UserService{
    @Override
    public void create() {
        System.out.println("创建了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void retrieve() {
        System.out.println("检索了一个用户");
    }

    @Override
    public void update() {
        System.out.println("更新了一个用户");
    }
}

创建日志(切面)

public class Log {
    public void beforeLog(){
        System.out.println("执行前置日志");
    }

    public void afterLog(){
        System.out.println("执行后置日志");
    }
}

编写applicationContext.xml文件
注册bean

    <!--注册bean-->
    <bean id="log" class="com.jas.Log"/>
    <bean id="userServiceImp" class="com.jas.service.UserServiceImp"/>

    <!--配置aop:定义切面,定义切入点,配置通知切入切入点的方式-->
    <aop:config>
        <!--定义切面-->
        <aop:aspect ref="log">
            <!--expression表达式定义切入点,即在目标对象中需要被拦截的方法-->
            <aop:pointcut id="pointcut" expression="execution(* com.jas.service.UserServiceImp.*(..))"/>

            <!--定义切面中的通知围绕切点的方式:before,after,after-returning,after-throwing,around-->
            <aop:before pointcut-ref="pointcut" method="beforeLog"/>
            <aop:after pointcut-ref="pointcut" method="afterLog"/>
        </aop:aspect>
    </aop:config>

测试

    @Test
    public void Test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //注意使用接口: Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
        UserService serviceImp = (UserService) context.getBean("userServiceImp");
        //调用目标对象方法  
        serviceImp.create();
    }
    
//output:   
执行前置日志
创建了一个用户
执行后置日志

注解实现

//定义切面

@Aspect
public class AnnotationLog {
    //切入点
    @Before("execution(* com.jas.service.UserServiceImp.*(..))")
    public void beforeLog(){
        System.out.println("执行前置日志");
    }

    @After("execution(* com.jas.service.UserServiceImp.*(..))")
    public void afterLog(){
        System.out.println("执行后置日志");
    }
}

配置xml文件注册bean和注解支持

    <!--注册bean-->
    <bean id="userServiceImp" class="com.jas.service.UserServiceImp"/>
    <bean id="annotationLog" class="com.jas.AnnotationLog"/>
    <!--增加aop注解支持-->
    <aop:aspectj-autoproxy/>

测试

@Test
public void Test(){
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //注意使用接口: Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
    UserService serviceImp = (UserService) context.getBean("userServiceImp");
    //调用目标对象方法
    serviceImp.create();
}

//output:
执行前置日志
创建了一个用户
执行后置日志

继承Spring API实现

以这种方式类似于直接定义通知,无需切面
前置日志

public class BeforeLog implements MethodBeforeAdvice {
    /*
    o:目标对象
    method:切入点,即被通知的方法
    objects:被通知方法的参数
    这三个参数也符合动态代理的参数
    */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getCanonicalName() + "的" + method.getName() + "方法执行了前置日志");
    }
}

后置日志

public class AfterLog implements AfterReturningAdvice {
    /*
    * o1:目标对象
    * o:返回对象
    * */
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println(o1.getClass().getCanonicalName()+"的"+method.getName()+"方法执行了后置日志");
    }
}

注册bean

<!--注册bean-->
<bean id="userServiceImp" class="com.jas.service.UserServiceImp"/>
<bean id="afterLog" class="com.jas.AfterLog"/>
<bean id="beforeLog" class="com.jas.BeforeLog"/>

配置aop

<!--aop配置-->
<aop:config>
    <!--无需切面-->
    <aop:pointcut id="pointcut" expression="execution(* com.jas.service.UserServiceImp.*(..))"/>
    <!--将通知切入切点-->
    <aop:advisor pointcut-ref="pointcut" advice-ref="afterLog"/>
    <aop:advisor pointcut-ref="pointcut" advice-ref="beforeLog"/>
</aop:config>

测试

    @Test
    public void Test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //注意使用接口: Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
        UserService serviceImp = (UserService) context.getBean("userServiceImp");
        //调用目标对象方法  
        serviceImp.create();
    }

//output:
com.jas.service.UserServiceImp的create方法执行了前置日志
创建了一个用户
com.jas.service.UserServiceImp的create方法执行了后置日志
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值