spring-aop学习笔记

本文详细介绍了Spring AOP的概念、动态代理的原理和实现方式,包括JDK动态代理和其在业务场景中的作用。接着,讲解了AspectJ在AOP中的应用,包括切面、连接点、通知等概念,以及如何通过注解定义切面的执行时间和位置。此外,还展示了如何使用AspectJ进行事务管理,包括XML配置和注解方式。整个过程旨在实现代码的解耦合和功能增强,简化事务处理。
摘要由CSDN通过智能技术生成

spring-aop笔记

动态代理

实现方式:

jdk动态代理:使用jdk中的proxy,method,InvocationHandler创建对象。
			  jdk动态代理要求目标类必须实现接口

动态代理的作用

1、在目标类源代码不变的情况下,增加功能。
2、减少代码的重复。
3、专注业务逻辑代码。
4、解耦合,让业务功能和其他的功能分离。

使用方式

1、创建目标接口和实现类

package com.bjpowernode.service;

public interface SomeService {

    void doSome();

    void doOther();
}

package com.bjpowernode.service.impl;

import com.bjpowernode.service.SomeService;
import com.bjpowernode.utils.ServiceTools;

public class SomeServiceImpl implements SomeService {

    @Override
    public void doSome() {
        System.out.println("执行业务方法 doSome ");
    }

    @Override
    public void doOther() {
       System.out.println("执行业务方法 doOther ");

    }
}

2、创建要增加的功能

package com.bjpowernode.utils;

import java.util.Date;

public class ServiceTools {

    public static void doLog(){
        System.out.println(new Date());
    }

    public static void doTrans(){
        System.out.println("提交事务");
    }
}

3、创建InvocationHandler的实现类

package com.bjpowernode.handler;

import com.bjpowernode.utils.ServiceTools;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

    private Object target = null;

    //因为是动态的,所以对象的类型不固定,用Object修饰,传进来是什么对象,就给什么对象代理
    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    //通过代理对象执行方法时,会调用这个方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy");
        //增加的功能
        ServiceTools.doLog();
        //执行目标类方法
        Object res = method.invoke(target,args);
        //增加的功能
        ServiceTools.doTrans();
        return res;
    }
}

4、创建代理对象,执行目标方法

package com.bjpowernode;

import com.bjpowernode.handler.MyInvocationHandler;
import com.bjpowernode.service.SomeService;
import com.bjpowernode.service.impl.SomeServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MyApp {

    public static void main(String[] args){

        //使用proxy创建代理对象
        //1、创建目标类对象
        SomeService target = new SomeServiceImpl();
        //2、创建InvocationHandler对象
        InvocationHandler handler = new MyInvocationHandler(target);
        //3、创建proxy代理对象
        SomeService proxy = (SomeService)Proxy.newProxyInstance(target.getClass().getClassLoader(),                                                             target.getClass().getInterfaces(),
                          		   handler); 				    

     //通过代理对象,执行目标类方法
        proxy.doSome();
    }
}


AOP(面向切面编程)

   基于动态代理,就是动态代理的一种规范化,把动态代理的实现步骤,方法都定义好,让开发人员用统一的方式,使用动态代理。
   
   
  aop(Aspect Orient Programming)
  
	Aspect :切面,给你的目标类增加的功能,就是切面。
	Orient :面向
	Programming :编程


 1、需要在分析项目功能时,找出切面
 2、合理安排切面的执行时间
 3、合理安排切面的执行位置

术语

1)Aspect:切面,表示增强的功能,非业务功能。
2)JoinPoint:连接点,连接业务方法和切面的位置,就是某类中的业务方法。
3)Pointcut:切入点,指多个连接点方法的集合,多个方法。
4)目标对象:给那个类的方法增加功能,这个类就是目标对象。
5)Advice:通知:表示切面功能执行的时间。

------------------------------------------------------------------------------------

一个切面有三个关键的要素:

	1、切面的功能代码,切面干什么
	2、切面的执行位置,使用pointcut表示切面执行的位置
	3、切面的执行时间,使用Advice表示,在目标方法前还是后

Aspectj实现AOP

aspectj实现方式:
		1、xml文件方式:配置全局事务
		2、注解方式:有5个注解

注解方式

切面的执行时间

   在aspectj中使用注解表示,也可以使用xml配置文件中的标签 
   
   	  1)@Before
      2)@AfterReturning
      3)@Around
      4)@AfterThrowing
      5)@After

切入点表达式

execution ([modifiers-pattern]? returnType-pattern  [declaring-type-pattern]?name-		 	pattern(param-pattern)  [throws-pattern]? )
   ↕↕↕↕
execution(访问权限 方法返回值类型 全路径类名+方法声明(参数) 异常类型)
  
 
	一共5个参数,有问号(?)的表示可以省略,每一个参数之间通过空格分隔,
	返回值类型和方法声明(参数)一定不可以省略

切入点表达式通配符

通配符 含义

  •             0到多个任意字符              
    

… 用在方法参数中,表示任意多个参数。 用在包名后,表示当前包以及子包路径

  • 用在类名后,表示当前类及其子类。用在接口后,表示当前接口及其实现类 
    

通配符示例

1、 execution(public * *(..)) -> 任意的public方法

2、 execution(* set*(..)) ->任意以set开头的方法

3、 execution(* com.xyz.service.*.*(..)) ->在service包下的任意类的任意方法

4、 execution(* com.xyz.service..*.*(..)) ->在service包和子包下的任意类的任意方法

5、 execution(* *..service.*.*(..)) ->所有的包下的service包的所有类的所有方法

使用方法

使用aspectj实现aop,目的是给已经存在的类和方法,增加一些功能,前提是不改变原来的代码


1、新建Maven项目

2、加入依赖
    1)spring依赖
    2)aspectj依赖

3、创建目标接口和实现类

4、创建一个切面类,就是一个普通类
    1)在类上加上@Aspect注解
    2)在类中定义方法,就是切面要执行的功能代码
       在@Aspect注解上加入通知注解,例如@Before,需要指定切入表达式

5、创建spring配置文件,声明对象,把对象交给spring容器统一管理,
   可以通过xml方式或注解方式
        1)声明目标类对象
        2)声明切面类对象
        3)声明Aspectj框架中的自动代理生成器。
                   自动代理生成器:用来完成代理对象的自动创建功能的。

6、测试:从spring容器中胡获取目标对象(实际上就是代理对象)。
        通过代理对象执行目标类的方法,实现aop。

XML方式一

切面类实现MethodBeforeAdvice接口,或者MethodAfterAdvice等接口,

然后重写接口方法,通过这个接口和重写的方法,就可以知道在目标方法执行前还是后执行切面方法。

//切面类
public class MyAspect implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("输出时间:"+new Date());
    }
}

deptServiceImpl:目标类对象

aspect:切面类对象

cut:切入点表达式,确定目标方法

    <bean id="deptServiceImpl" class="com.bjpowernode.service.DeptServiceImpl"/>

    <bean id="aspect" class="com.bjpowernode.aspect.MyAspect"/>

    <aop:config>
        <aop:pointcut id="cut" expression="execution(* com.bjpowernode.service.DeptServiceImpl.*(..))"/>
        <aop:advisor advice-ref="aspect" pointcut-ref="cut"/>
    </aop:config>

XML方式二

//切面类,不实现任何接口,方法也是普通方法
public class MyAspect  {

    public void beforeAspect(){
        System.out.println("前置通知2");
    }
}

deptserviceImpl:目标类对象

aspect:切面类对象,在没有在aop:aspect标签使用时,就是一个普通对象

因为切面类没有实现方式一的接口,通过<aop:aspect ref=“aspect”>来确定切面对象

cut:切入点表达式,确定目标方法

aop:before标签 :确定执行切面方法的时机

method=“beforeAspect”:确定那个方法时切面方法

通过aop:aspect ref=“aspect”,确定切面对象,然后aop:before method=“beforeAspect” ,确定切面方法和执行时机,pointcut-ref="cut"确定目标类对象和目标方法

通过getBean方法获得目标对象的代理对象

  <!--目标对象-->
    <bean id="deptserviceImpl" class="com.bjpowernode.impl.DeptServiceImpl"/>

    <!--切面对象-->
    <bean id="aspect" class="com.bjpowernode.aspect.MyAspect"/>

    <!--AOP-->
    <aop:config>
        <aop:aspect ref="aspect">
            <aop:pointcut id="cut" expression="execution(* com.bjpowernode.impl.DeptServiceImpl.*(..))"/>
            <aop:before method="beforeAspect" pointcut-ref="cut"/>
        </aop:aspect>
    </aop:config>

AOP实现事务

事务也是AOP的一种,只是spring框架把事务做好了,相当于框架就已经把事务的切面类写好了,我们只需要写目标类就可以了。

事务相当于环绕通知。

XML方式

事务需要的依赖

 	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.3.18</version>
    </dependency>

transcation:事务管理对象,需要给他一个数据源

service:目标对象

aspect:spring框架实现好的事务切面类

	tx:method name="*",给所有的方法都加上事务





<bean>

    <!--数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="Yjznzsa666"/>
        <property name="maxActive" value="20"/>
    </bean>

    <!--目标对象-->
    <bean id="service" class="com.bjpowernode.impl.DeptServiceImpl"/>

  
 	<!--事务管理对象-->   
<bean id="transcation" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
  
	<!--切面对象,由spring框架提供-->
    <tx:advice id="aspect" transaction-manager="transcation">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="cut" expression="execution(* com.bjpowernode.impl.DeptServiceImpl.*(..))"/>
        <aop:advisor advice-ref="aspect" pointcut-ref="cut"/>
    </aop:config>
  
  
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值