Java研学-Spring AOP

一 概述

1 介绍

  AOP(Aspect Oriented Programming)面向切面编程技术,将一个个的横切关注点放到模块中,称之为切面。每一个的切面都能影响业务的某一种功能,切面的目的是功能增强,日志切面就是一个横切关注点,应用中方法需做日志记录的只需要插入日志的切面即可。(动态代理就可以实现 AOP)

  AOP 可将与业务无关,但为业务模块所共同调用的逻辑或责任(如事务处理、日志管理、权限控制等)封装起来,减少系统冗余代码,降低模块间耦合度,增强可拓展性和可维护性。将业务方法中与业务无关的操作抽离到不同的对象中,最后使用动态代理的方式组合起来,动态地为类增加功能。
AOP原理图

2 名词解释

Joinpoint:连接点,指需要被增强的方法。
Pointcut:切入点,哪些包中的哪些类中的哪些方法,可认为是连接点的集合。
Advice:增强,当拦截到 Joinpoint 之后,在方法执行的什么时机(when)做什么样(what)的增强。
根据时机分为:前置增强、后置增强、异常增强、最终增强、环绕增强。
Aspect:切面,Pointcut + Advice,去哪些地方 + 在什么时候 + 做什么增强。
Target:被代理的目标对象。
Weaving:织入,把 Advice 加到 Target 上之后,创建出 Proxy 对象的过程。
Proxy:一个类被 AOP 织入增强后,产生的代理类。
where:去哪里做增强。

3 AspectJ

  AOP 思想的实现有两种方式 Spring AOP 和 AspectJ。与原始 Spring AOP 编程相比 AspectJ(比如切入点表达式)开发更为简洁。AspectJ 是一个面向切面的框架,它使用 Java 对 AOP 进行了实现。

4 AspectJ 切入点语法

// execution(修饰符.返回类型.全限定名.方法名.方法参数.异常类型)
// 其中修饰符可以省略,返回类型可用*号代替,全限定名中的包结构每个部分都可用*号代替但只表示一个单词
// 对于实现类可用*ServiceImpl代替多个ServiceImpl实现类,方法也可设为*,参数可用..代替
// execution()为切入点表达式 ()内为切入点 此方法可确定到指定类的指定方法进行增强
// * :匹配任何部分,只能表示一个单词
// .. :可用于全限定名中(表示当前包及子包)和方法参数中(表示子 0 到 N 个参数)
// 例子  第一个*号后面有空格
execution(* cn.tj.ssm.service.impl.*ServiceImpl.*(..))

二 AOP配置(XML)

1 添加依赖

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

2 事务(增强)类

public class TransactionManager {
    /*开启事务*/
    public void begin(){
        System.out.println("事务开启了.....");
    }
    /*提交事务*/
    public void commit(){
        System.out.println("事务提交了........");
    }
    /*回滚事务*/
   public void rollback(){
       System.out.println("事务回滚了.........");
   }
}

3 目标对象 接口实现类 – EmployeeServiceImpl

// 接口
public interface EmployeeService {
    /*员工保存*/
    public  int save(String username,String password);
}

public class EmployeeServiceImpl implements EmployeeService {
// save 此方法为连接点
    @Override
    public int save(String username, String password) {
        System.out.println("员工姓名:"+username+"密码:"+password);
        return 0;
    }
}

4 配置文件 – spring-core.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--真实目标对象-->
    <bean id="employeeService" class="cn.tj.service.impl.EmployeeServiceImpl"></bean>
    <!--增强类对象-->
    <bean id="transactionManager" class="cn.tj.tx.TransactionManager"></bean>
    <!--声明(开启)aop 将增强对象的方法放入目标对象中 引入约束后可使用-->
    <aop:config >
        <!--定义切面 通过ref关联增强类对象-->
        <aop:aspect ref="transactionManager">
            <!--切入点-->
            <aop:pointcut id="pc"
                          expression="execution(* cn.tj.service.impl.*ServiceImpl.*(..))"/>
            <!--前置增强(before) 针对pc切入点做前置增强 begin是增强类中的方法-->
            <aop:before method="begin" pointcut-ref="pc"></aop:before>
            <!--后置增强-->
            <aop:after-returning method="commit" pointcut-ref="pc"></aop:after-returning>
            <!--异常增强-->
            <aop:after-throwing method="rollback" pointcut-ref="pc"></aop:after-throwing>
        </aop:aspect>
    </aop:config>
</beans>

5 测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-core.xml")
public class EmployeeServiceTest {
	// 注入对象直接调用即可
    @Autowired
    private EmployeeService employeeService;
    @Test
    public void emp_save() {
       employeeService.save("叶凡","admin");
    }
}

6 切换动态代理 – 修改配置文件

<!--Spring AOP在目标对象实现接口时,默认使用 JDK 动态代理。若想使用 CGLIB 动态代理,需配置如下-->
<aop:config proxy-target-class="true">
    <!--内部与jdk相同-->
</aop:config>

三 AOP配置(注解)

1 目标对象 接口实现类 – EmployeeServiceImpl

// 接口
public interface EmployeeService {
    /*员工保存*/
    public  int save(String username,String password);
}

public class EmployeeServiceImpl implements EmployeeService {
	// save 此方法为连接点
    @Override
    public int save(String username, String password) {
        System.out.println("员工姓名:"+username+"密码:"+password);
        return 0;
    }
}

2 事务(增强)类

// 交给Spring容器处理 并设置为切面对象
@Component
@Aspect
public class TransactionManager {
    /*切入点表达式方法*/
    @Pointcut("execution(* cn.tj.service.impl.*ServiceImpl.*(..))")
    public void pc(){}
    /*开启事务 添加对应注解 关联切入点 或用@Before(Pointcut="切入点表达式")*/
    @Before("pc()")
    public void begin(){
        System.out.println("事务开启了.....");
    }
    /*提交事务*/
    @AfterReturning( "pc()")
    public void commit(){
        System.out.println("事务提交了........");
    }
    /*回滚事务*/
    @AfterThrowing("pc()")
   public void rollback(){
       System.out.println("事务回滚了.........");
   }
}

3 配置文件 – spring-core.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--真实目标对象-->
    <bean id="employeeService" class="cn.tj.service.impl.EmployeeServiceImpl"></bean>
    <!--增强类对象-->
    <bean id="transactionManager" class="cn.tj.tx.TransactionManager"></bean>
    <!--开启aop注解扫描 为配置AspectJ切面的bean创建代理,并将切面织入到这些 bean 中-->
    <aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
</beans>

4 测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-core.xml")
public class EmployeeServiceTest {
	// 注入对象直接调用即可
    @Autowired
    private EmployeeService employeeService;
    @Test
    public void emp_save() {
       employeeService.save("叶凡","admin");
    }
}

5 切换动态代理 – 修改配置文件

<aop:aspectj-autoproxy proxy-target-class="true"/>
  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泰勒疯狂展开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值