前置增强,后置增强,异常增强,最后增强
基于maven项目的pom.xml配置:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.1.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
在本篇文章中,bean层,dao层,service层都和前一篇文章一样,详情请看
此处只写不一样的配置。
动态代理层
MethodAdvice.java
package com.proxy;
// 增强方法
public class MethodAdvice {
public void before() {
System.out.println("前置增强");
}
public void afterRunning() {
System.out.println("后置增强");
}
public void afterThrowing() {
System.out.println("异常增强");
}
public void after() {
System.out.println("最终增强");
}
}
spring配置类:
beans.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="txManager" class="com.service.impl.TransactionManager"/>
<bean id="employeeDao" class="com.dao.EmployeeDaoImpl" />
<bean id="employeeService" class="com.service.impl.EmployeeServiceImpl">
<property name="dao" ref="employeeDao" />
</bean>
<bean id="employeeService2" class="com.service.impl.EmployeeServiceImpl2">
<property name="dao" ref="employeeDao" />
</bean>
<bean id="methodAdvice" class="com.proxy.MethodAdvice"/>
<!--
相关概念:
1、joinpoint:连接点,也就是要增强的方法
2、pointcut:切入点,它是指对哪些类中的哪些方法做增强,是连接点的集合
3、advice:它对方法那个位置做什么样的增强。根据位置分为:前置增强、后轩增强、异常增强、最终增强
4、aspect:切面,它是pointcut和advice的整体。
配置AOP
使用aop:config来配置aop
如果想要使用CGLIB方式,则需要在aop:config标签上添加proxy-target-class="true"
-->
<aop:config proxy-target-class="true">
<!-- 使用aop:aspect来定义一个切面,ref引用的已经存在的切面bean -->
<aop:aspect ref="methodAdvice">
<!-- pointcut配置切入点,
id是切入点的名称,需要唯一
expression是定义连接点的表达式,表达的解读:
execution(* com.service..*.*(..))
任意访问修改符,在com.service包及其子包下的任意类中的任意方法,不管该方法是否有参数
-->
<aop:pointcut id="pt" expression="execution(* com.service..*.*(..))"/>
<!--
aop:before配置前置增强,属性说明:
method:用于指定要增强的方法
pointcut-ref:引用切入点表达式,也就是说要对哪些类中的方法做增强
-->
<aop:before method="before" pointcut-ref="pt"/>
<!-- 后置增强 -->
<aop:after-returning method="afterRunning" pointcut-ref="pt"/>
<!-- 异常增强 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
<!-- 最终增强 -->
<aop:after method="after" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
</beans>
CGLIBDynamicProxyTest.java动态代理测试
package com.test.dyni.proxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import com.bean.Employee;
import com.service.impl.EmployeeServiceImpl2;
// CGLIB动态代理测试类
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:beans.xml")
public class CGLIBDynamicProxyTest {
@Autowired
private EmployeeServiceImpl2 service;
@Test
public void testSave() {
System.out.println(service.getClass());
service.save(new Employee());
}
@Test
public void testUpdate() {
service.update(new Employee());
}
}
JdkDyniProxyTest 动态代理测试
package com.test.dyni.proxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import com.bean.Employee;
import com.service.EmployeeService;
/**
* Jdk动态代理测试类
*/
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:beans.xml")
public class JdkDyniProxyTest {
@Autowired
private EmployeeService service;
@Test
public void testSave() {
service.save(new Employee());
}
@Test
public void testUpdate() {
service.update(new Employee());
}
}
环绕增强方式:
动态代理层:
TransactionManager.java
package com.proxy;
import java.util.Arrays;
import org.aspectj.lang.ProceedingJoinPoint;
// 模拟事务管理器
public class TransactionManager {
public void begin() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
public void close() {
System.out.println("释放资源");
}
/**
* 要想获取到异常信息,需要在spring的配置文件中配置
* thowing="变量名称"
* <aop:after-throwing method="rollback" pointcut-ref="pt" throwing="ex"/>
* 然后在此方法中添加一个Throwable类型的参数,参数名称为指定的变量名称
* @param ex
*/
public void rollback(Throwable ex) {
System.out.println("回滚事务," + ex.getMessage());
}
// 环绕增强方法
public Object around(ProceedingJoinPoint pjp) {
Object proceed = null;
begin();
try {
System.out.println("代理对象:" + pjp.getThis().getClass());
System.out.println("目标对象:" + pjp.getTarget().getClass());
System.out.println("被增强方法参数:" + Arrays.toString(pjp.getArgs()));
System.out.println("当前连接点签名:" + pjp.getSignature());
System.out.println("当前连接点类型:" + pjp.getKind());
// 核心方法
proceed = pjp.proceed();
commit();
} catch (Throwable e) {
rollback(e);
} finally {
close();
}
return proceed;
}
}
spring配置方式:
beans.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="employeeDao" class="com.dao.EmployeeDaoImpl" />
<bean id="employeeService" class="com.service.impl.EmployeeServiceImpl">
<property name="dao" ref="employeeDao" />
</bean>
<!-- 用于切面的bean -->
<bean id="aspect" class="com.proxy.TransactionManager" />
<!-- 配置aop -->
<aop:config>
<aop:aspect ref="aspect">
<aop:pointcut expression="execution(* com.service..*.*(..))" id="pt"/>
<!-- <aop:before method="begin" pointcut-ref="pt"/>
<aop:after-returning method="commit" pointcut-ref="pt"/>
<aop:after-throwing method="rollback" pointcut-ref="pt" throwing="ex"/>
<aop:after method="close" pointcut-ref="pt"/> -->
<!-- 配置环绕增强 -->
<aop:around method="around" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
</beans>
环绕增强测试:
AOPTest.java
package com.test.dyni.proxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import com.bean.Employee;
import com.service.EmployeeService;
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:beans.xml")
public class AOPTest {
@Autowired
private EmployeeService service;
@Test
public void testSave() {
service.save(new Employee());
}
@Test
public void testUpdate() {
service.update(new Employee());
}
}