[go: nahoru, domu]

Skip to content

Commit

Permalink
feat: 新增Spring代理模式以及AOP入门
Browse files Browse the repository at this point in the history
  • Loading branch information
Poison02 committed Jun 26, 2023
1 parent 0647c14 commit 35d1b56
Show file tree
Hide file tree
Showing 13 changed files with 455 additions and 0 deletions.
38 changes: 38 additions & 0 deletions spring6/dynamic-proxy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
17 changes: 17 additions & 0 deletions spring6/dynamic-proxy/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cdu.zch</groupId>
<artifactId>dynamic-proxy</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cdu.zch.proxy.client;

import cdu.zch.proxy.service.OrderService;
import cdu.zch.proxy.service.OrderServiceImpl;
import cdu.zch.proxy.service.TimerInvocationHandler;
import cdu.zch.proxy.util.ProxyUtil;

import java.lang.reflect.Proxy;

/**
* 客户端程序
* @author Zch
* @date 2023/6/26
**/

public class Client {

public static void main(String[] args) {
// 创建目标对象
OrderService target = new OrderServiceImpl();
// 创建代理对象
/*
1. newProxyInstance 新建代理对象
通过调用这个方法可以创建代理对象
本质上,newProxyInstance方法的执行,做了两件事
1. 在内存中动态的生成了一个代理类的字节码class
2. new对象,同归哦内存中生成的代理类这个代码,实例化了代理对象
2. 三个参数:
ClassLoader loader:
类加载器,在内存中生成的字节码也是class文件,要执行也得先加载到内存中。
这里需要类加载器,并且必须和代理类的类加载器是同一个
Class<?>[] interfaces:
代理类和目标类要实现同一个或者同一些接口
在内存中生成代理类的时候,这个代理类是需要你告诉它实现哪些接口的
InvocationHandler h:调用处理器,是一个接口
编写的就是:增强代码
既然是接口,就要写接口的实现类
这个接口实现类只需要写一次即可,不会类爆炸
注意:代理对象和目标对象实现了接口,所以可以向下转型
*/
/*OrderService proxyObj = (OrderService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new TimerInvocationHandler(target));*/
// 这里还可以使用封装的工具类
OrderService proxyObj = (OrderService) ProxyUtil.newProxyInstance(target);
// 调用代理对象的代理方法
// 注意:调用代理对象的代理方法的时候,需要保证目标对象的目标方法需要执行
proxyObj.generate();
proxyObj.modify();
proxyObj.detail();
String name = proxyObj.getName();
System.out.println(name);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cdu.zch.proxy.service;

/**
* @author Zch
* @date 2023/6/26
**/
public interface OrderService { // 公共接口

String getName();

/**
* 生成订单
*/
void generate();

/**
* 修改订单信息
*/
void modify();

/**
* 查看订单信息
*/
void detail();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cdu.zch.proxy.service;

/**
* @author Zch
* @date 2023/6/26
**/
public class OrderServiceImpl implements OrderService{ // 目标对象
@Override
public String getName() {
System.out.println("getName()方法执行");
return "zhangsan";
}

// 目标方法
@Override
public void generate() {
// 模拟生成订单的耗时
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("订单已生成");
}

@Override
public void modify() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("订单已修改");
}

@Override
public void detail() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("订单详情");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cdu.zch.proxy.service;

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

/**
* 专门负责计时的一个调用处理器对象。
* 在这个调用处理器中编写计时相关的增强代码
* 只需要写一次就行了
* @author Zch
* @date 2023/6/26
**/
public class TimerInvocationHandler implements InvocationHandler {

// 目标对象
private Object target;

public TimerInvocationHandler(Object target) {
this.target = target;
}

/*
1. 为什么强行要求必须实现InvocationHandler接口?
因为一个类实现接口就必须实现接口中的方法
以下这个方法必须是invoke(),因为jdk在底层已经写好了
注意:invoke不是我们调用的,而是jdk调用
2. invoke()什么时候调用?
当代理对象调用代理方法的时候,注册在InvocationHandler调用处理器当中的invoke()会被jdk调用
3. invoke 的三个参数
invoke方法是JDK负责调用的,调用的时候JDK自动传过来
Object proxy 代理对象的引用
Method method 目标对象的目标方法,就是要使用它!
Object[] args 目标方法的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这个接口的目的就是为了写增强代码
// System.out.println("增强方法1");
long begin = System.currentTimeMillis();
// 调用目标对象的目标方法
// 方法四要素:哪个对象、哪个方法、传什么参数、返回什么
Object retValue = method.invoke(target, args);
long end = System.currentTimeMillis();
System.out.println("执行了" + (end - begin)+ "毫秒");
// System.out.println("增强方法2");
// 注意这个invoke方法的返回值,如果代理对象调用代理方法之后需要返回结果的话,这里也需要返回!
return retValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cdu.zch.proxy.util;

import cdu.zch.proxy.service.OrderService;
import cdu.zch.proxy.service.TimerInvocationHandler;

import java.lang.reflect.Proxy;

/**
* @author Zch
* @date 2023/6/26
**/
public class ProxyUtil {

/**
* 封装一个工具方法,可任意通过这个方法调用,实现动态代理
*/
public static Object newProxyInstance(Object target) {
Object proxyObj = Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new TimerInvocationHandler(target));
return proxyObj;
}

}
38 changes: 38 additions & 0 deletions spring6/static-proxy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
17 changes: 17 additions & 0 deletions spring6/static-proxy/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cdu.zch</groupId>
<artifactId>static-proxy</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

</project>
38 changes: 38 additions & 0 deletions spring6/static-proxy/src/main/java/cdu/zch/proxy/client/Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cdu.zch.proxy.client;

import cdu.zch.proxy.service.OrderService;
import cdu.zch.proxy.service.OrderServiceImpl;
import cdu.zch.proxy.service.OrderServiceProxy;

/**
* @author Zch
* @date 2023/6/26
**/
public class Test {

public static void main(String[] args) {
/*OrderService orderService = new OrderServiceImpl();
orderService.generate();
orderService.modify();
orderService.detail();*/

/*
代理模式:
优点1:解决了OCP问题
优点2:采用代理模式的has a,可以降低耦合度
缺点:目前使用的静态代理,类爆炸,假设接口有很多,就必须写很多代理类,不好维护...
后面会使用动态代理,添加了字节码技术,可以在内存中动态的生成class字节码,这个字节码就是代理类
在内存中动态的生成字节码代理类的技术,叫做动态代理
*/
// 下面使用代理
// 创建目标对象
OrderService target = new OrderServiceImpl();
// 创建代理对象
OrderService proxy = new OrderServiceProxy(target);
// 调用代理对象的方法
proxy.generate();
proxy.modify();
proxy.detail();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cdu.zch.proxy.service;

/**
* @author Zch
* @date 2023/6/26
**/
public interface OrderService { // 公共接口

/**
* 生成订单
*/
void generate();

/**
* 修改订单信息
*/
void modify();

/**
* 查看订单信息
*/
void detail();

}
Loading

0 comments on commit 35d1b56

Please sign in to comment.