Spring核心思想-AOP面向切面编程

AOP(Aspect-Oriented Programming: 面向切面编程):

将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面”(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;

Spring AOP 基于动态代理实现:

○ 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);
  ○ 如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类);


AOP通知类型

AOP将抽取出来的共性功能称为通知;通知类型:以通知在上下文中的具体位置作为划分
  前置通知(Before)
  返回通知(After-returning)
  异常通知(After-throwing)
  后置通知(After)
  环绕通知(Around)

AOP连接点(Join point)

  AOP将所有的方法都视为连接点,不管是接口里面的抽象方法,还是实现类里面的重写方法,都是连接点

AOP切点(Pointcut)

 AOP将可能被抽取共性功能的方法称为切入点。切入点是连接点的子集

AOP目标对象(Target):

就是挖掉功能的方法对应的类生的对象,这种对象是无法直接完成最终工作的

AOP织入(Weaving):

就是将挖掉的功能回填的动态过程

AOP切面:切点+通知

SpringAOP+AspectJ实现步骤

1.添加依赖,aop与aspectj表达式的依赖
2.创建spring的主配置文件,bean内的命名空间要添加aop的
3.创建业务代码并编写日志记录代码(事务管理代码)
4.将业务层与日志记录层注入spring容器
5.<aop:config>--aop配置
        aop:aspect--aop切面
               aop:before--通知内容与通知类型


切点表达式配置语法:


    execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))
    eg:    

execution(public void com.apesource.service.ServiceImp.findAll())


    1.修饰符可以省略代表任意
        execution(返回值 包名称.类名称.方法名称(参数列表))
    2.返回值可以使用“*”代表任意
        execution(* 包名称.类名称.方法名称(参数列表))
    3.包名可以使用“*”代表任意名称
        execution(* *.*.*.类名称.方法名称(参数列表))
    4.包名可以使用“..”代表任意个数
        execution(* *...类名称.方法名称(参数列表))
    5.类名与方法名可以使用“*”代表任意
        execution(* *...*.*(参数列表))
    6.参数列表可以使用".."代表任意个数任意类型
        execution(* *...*.*(..))
        如果有参数
            int======>int
            String===>java.lang.String

代码示例

public interface IAccountService {
    /**
     * 新增
     * */
    public void save(int i);
    /**
     * 修改
     * */
    public void update();
    /**
     * 删除
     * */
    public int delete();
}


//实现类
public class AccountServiceImpl implements IAccountService{
    @Override
    public void save(int i) {
        System.out.println("业务层的新增方法:"+i);
//        int a=10/0;//模拟异常
    }
    @Override
    public void update() {
        System.out.println("业务层的修改方法:");
    }

    @Override
    public int delete() {
        System.out.println("业务层的删除方法:");
        return 0;
    }
}




public class Logger {
    public void beforeMethod(){
        System.out.println("日志的前置通知");
    }
    public void returnMethod(){
        System.out.println("日志的返回通知");
    }
    public void throwMethod(){
        System.out.println("日志的异常通知");
    }
    public void afterMethod(){
        System.out.println("日志的后置通知");
    }

    public Object aroundMethod(ProceedingJoinPoint pjp){
        Object obj=null;
        try{
            System.out.println("环绕通知===前置通知");
            //切点方法
           Object[] ars= pjp.getArgs();
           obj=pjp.proceed(ars);
            System.out.println("环绕通知===返回通知");
        }catch (Throwable t){
            t.printStackTrace();
            System.out.println("环绕通知===异常通知");
        }finally {
            System.out.println("环绕通知===后置通知");
            return obj;
        }
    }
}


//applicationContext.xml类

<!--注入业务层-->
    <bean id="service" class="com.apesource.service.AccountServiceImpl"></bean>
    <!--注入日志记录层(通知)-->
    <bean id="logger" class="com.apesource.util.Logger"></bean>

    <!--配置AOP-->
    <aop:config>
        <!--配置切面-->
        <aop:aspect id="aopAspect" ref="logger">
            <!--切点-->
            <aop:pointcut id="dian" expression="execution(* com.apesource.service.*.*(..))"/>
            <!--通知-->
            <!--<aop:before method="beforeMethod" pointcut-ref="dian"></aop:before>
            <aop:after-returning method="returnMethod" pointcut-ref="dian"></aop:after-returning>
            <aop:after-throwing method="throwMethod" pointcut-ref="dian"></aop:after-throwing>
            <aop:after method="afterMethod" pointcut-ref="dian"></aop:after>-->
            <!--环绕通知-->
            <aop:around method="aroundMethod" pointcut-ref="dian"></aop:around>
        </aop:aspect>
    </aop:config>



//Test类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test03 {
    @Autowired
    public IAccountService service;
    @Test
    public void test1(){
        service.save(1);
        System.out.println("-------------------------");
        service.update();
        System.out.println("-------------------------");
        service.delete();
        System.out.println("-------------------------");
    }
}

运行结果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值