Spring-AOP(三种代理比较)
2019-12-18 本文已影响0人
HeloWxl
目录
- 静态代理
- 动态代理
- AOP实现(基于XML)
项目结构
项目结构.png需求
- 现在有一个学生表,我们需要记录它的增加和删除操作。
pom.xml
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!--spring aop + aspectj-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
Student
public class Student {
String name;
Integer age;
String address;
//省略getter,setter方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
StudentService
public interface StudentService {
/**
* 添加学生
* @param student
* @return
*/
int addStudent(Student student);
/**
* 删除学生
* @param name
* @return
*/
int deleteStudent(String name);
}
StudentServiceImpl
public class StudentServiceImpl implements StudentService {
public int addStudent(Student student) {
System.out.println("添加学生:"+student.toString());
return 1;
}
public int deleteStudent(String name) {
System.out.println("删除学生:"+name);
return 1;
}
}
静态代理
MyTransaction
public class MyTransaction {
//开启事务
public void before(){
System.out.println("开启事务");
}
//提交事务
public void after(){
System.out.println("提交事务");
}
}
ProxyStudent
public class ProxyStudent implements StudentService {
//真实类
private StudentService studentService;
//事务类
private MyTransaction transaction;
//使用构造函数实例化
public ProxyStudent(StudentService studentService,MyTransaction transaction){
this.studentService = studentService;
this.transaction = transaction;
}
public int addStudent(Student student) {
transaction.before();
studentService.addStudent(student);
transaction.after();
return 1;
}
public int deleteStudent(String name) {
transaction.before();
studentService.deleteStudent("HeloWxl");
transaction.after();
return 1;
}
}
测试
/**
* @Description //TODO 静态代理实现
*/
@Test
public void TestStaticProxy() {
StudentService studentService = new StudentServiceImpl();
MyTransaction transaction = new MyTransaction();
ProxyStudent proxyStudent = new ProxyStudent(studentService,transaction);
//添加
Student student = new Student();
student.setName("HeloWxl");
student.setAddress("安徽合肥");
student.setAge(22);
proxyStudent.addStudent(student);
//删除
proxyStudent.deleteStudent("wangxl");
}
测试结果
静态代理的缺点:
- 代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
- 如果接口增加一个方法,比如 StudentService 增加修改 updateStudent()方法,则除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
动态代理
ObjectInterceptor
public class ObjectInterceptor implements InvocationHandler {
//目标类
private Object target;
//切面类(这里指事务类)
private MyTransaction transaction;
//通过构造器赋值
public ObjectInterceptor(Object target,MyTransaction transaction){
this.target = target;
this.transaction = transaction;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//开启事务
this.transaction.before();
//调用目标类方法
Object object = method.invoke(this.target, args);
//提交事务
this.transaction.after();
return object;
}
}
测试方法
@Test
public void TestJdkProxy() {
//目标类
Object target = new StudentServiceImpl();
//事务类
MyTransaction transaction = new MyTransaction();
ObjectInterceptor proxyObject = new ObjectInterceptor(target, transaction);
/**
* 三个参数的含义:
* 1、目标类的类加载器
* 2、目标类所有实现的接口
* 3、拦截器
*/
StudentService studentService = (StudentService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), proxyObject);
Student student = new Student();
student.setName("HeloWxl");
student.setAddress("安徽合肥");
student.setAge(22);
studentService.addStudent(student);
studentService.deleteStudent("HeloWang");
}
测试结果
AOP实现
bean.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
">
<bean id="studentService" class="com.springaop.service.impl.StudentServiceImpl" ></bean>
<!-- <bean id="loggerAfterRun" class="com.springaop.aop.afterreturning.LoggerAfterReturnningXml" ></bean>-->
<bean id="transaction" class="com.springaop.aop.staticProxy.MyTransaction" ></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.springaop.service.impl.*.*(..))"/>
<aop:aspect ref="transaction">
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<aop:after-returning method="after" pointcut-ref="pointcut"></aop:after-returning>
</aop:aspect>
</aop:config>
</beans>
测试
@Test
public void TestAop1() {
//从spring容器获得 //1 获得容器
String xmlPath = "bean.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
//2获得内容 --不需要自己new,都是从spring容器获得
StudentService studentService = (StudentService) applicationContext.getBean("studentService");
//添加
Student student = new Student();
student.setName("HeloWxl");
student.setAddress("安徽合肥");
student.setAge(22);
studentService.addStudent(student);
//删除
studentService.deleteStudent("HeloWxl");
}