自学spring的回顾(2/3)
aop概述
1、aop是动态代理的一种规范化,它的底层是动态代理机制,是面向切面编程。
切面(Aspect):切面,给你的目标类增加的功能,就是切面。一般都是非业务方法,独立使用。
它有两种动态代理方式:
(1)jdk动态代理:使用jdk反射中类的实现创建动态代理对象的方式(要求必须有接口)
(2)cglib动态代理:通过类之间继承来创建动态代理对象的方式
2、作用:在不修改源代码的基础上增强功能。
3、一般在处理事务,日志,统计信息,参数检查,权限验证等方面上使用。
aop中的术语
1、Aspect:切面,表示给方法提供增强的功能。
2、Pointcut:切入点,指多个连接点方法的结合。连接点表示切面功能的执行位置。
3、Advice:通知,通知表示切面功能执行的时间。
aop在spring中的实现
1、在spring中的aspectj框架实现的aop有两种实现方法:
(1)使用注解
(2)xml配置文件的标签
2、在增强方法上的注解的基本语法:
@通知(value=“execution(切入点表达式)”)
注:如果动态代理没有用到接口,实现的就是cglib动态代理。但是有接口,也可以使用cglib。
在配置文件中写入<aop:aspectj-autoproxy proxy-target-class=“true”/>即可表达cglib实现。
aop常见的通知和切入点表达式
1、常见通知:
(1)@Before:切面功能在目标方法执行之前执行。
(2)@AfterReturning:切面功能在目标方法之后执行,并能获取目标方法的返回值,注解属性要有returning,并且值和切面方法中的第一个参数相同。
(3)@Around:切面功能在目标方法之前和之后执行,控制目标方法的访问,修改返回值。方法参数中要有ProceedingJoinPoint,在方法中声明ProceedingJoinPoint对象.proceed();相当于method.invoke,代表目标方法的执行。
(4)@AfterThrowing:异常通知后切面功能执行。
(5)@After:切面功能在目标方法执行之后执行
注:@Pointcut:代表重复的execution,减少开发,它并不是通知。JoinPoint使用在切面方法中,JoinPoint对象能够获取目标方法的信息。
2、切入点表达式:
execution(类型修饰符(可选),方法返回值类型,包名(可选),方法名(方法参数),throw(可选))
常用*和.来通配符表示
例子:
execution(public * *(..)) \\表示任意公共方法
execution(* set*(..)) \\表示任何一个以set开头的方法
execution(* com.xad.service.*.*(..)) \\表示包下任意的类的方法
aop在spring中的实现
1、新建maven项目
2、加入依赖
(1)spring依赖
(2)aspectJ依赖
(3)单元测试依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
3、创建目标类:
接口和它的实现类
public interface SomeService {
public void doSome(String name,Integer age);
}
public class SomeServiceImpl implements SomeService {
@Override
public void doSome(String name, Integer age) {
System.out.println("doSome()");
}
}
4、创建切面类:普通类
(1)在类的上面加入@Aspect
(2)在类中定义方法,方法就是切面要执行的功能代码,并在
方法上面加入指定的通知注解
@Aspect
public class MyAspect {
@Before(value = "execution(public void com.my.ba01.SomeServiceImpl.doSome(String,Integer))")
public void myBefore(){
System.out.println("增强功能");
}
}
5、创建spring的配置文件:声明对象,把对象交给容器统一管理
声明对象可以使用注解或者xml配置文件
(1)声明目标对象
(2)声明切面类对象
(3)声明aspectJ框架中的自动代理生成器标签
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="someService" class="com.my.SomeServiceImpl"></bean>
<bean id="myAspect" class="com.my.MyAspect"></bean>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
6、创建测试类,从spring容器中获取目标对象
然后执行代理对象的方法,来实现功能增强
@Test
public void test01(){
String config="applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
SomeService someServer = (SomeService) applicationContext.getBean("someService");
someServer.doSome("asda",123);
}
}