代理是一种设计模式,在软件设计中,有时候会出现用户不想或者不能直接引用一个对象的情况,这时候就可以通过代理对象在用户和目标对象之间充当一个中介的作用。
静态代理
// 定义接口
public interface Greeting {
void sayHello(String name);
}
// 实现类
public class GreetingImpl implements Greeting {
@Override
public void sayHello(String name) {
System.out.println("hello: " + name);
}
}
// 调用
public class Client {
public static void welcome(Greeting greeting, String name){
greeting.sayHello(name);
}
public static void main(String[] args) {
Greeting greeting = new GreetingImpl();
welcome(greeting, "java");
}
}
// 结果:hello: java
// 在不修改实现类的情况下,给输出增加日志功能
// 创建代理类
public class GreetingProxy implements Greeting{
private Greeting greeting;
public GreetingProxy(Greeting greeting){
this.greeting = greeting;
}
@Override
public void sayHello(String name) {
System.out.println("method start");
greeting.sayHello(name);
System.out.println("method end");
}
}
// 再次调用
public class Client {
public static void main(String[] args) {
Greeting greeting = new GreetingImpl();
GreetingProxy proxy = new GreetingProxy(greeting);
proxy.sayHello("java");
}
}
// 输出
method start
hello: java
method end
动态代理
// 创建动态代理
public class LogHandler implements InvocationHandler {
private Object originObj;
public Object bind(Object originObj){
this.originObj = originObj;
return Proxy.newProxyInstance(
originObj.getClass().getClassLoader(),
originObj.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + ": start");
Object result = method.invoke(originObj, args);
System.out.println(method.getName() + ": end");
return result;
}
}
// 调用
public class Client {
public static void main(String[] args) {
Greeting greeting = new GreetingImpl();
LogHandler handler = new LogHandler();
Greeting proxy = (Greeting) handler.bind(greeting);
proxy.sayHello("java");
}
}
// 结果
sayHello: start
hello: java
sayHello: end
AOP
SpringAOP可以帮助我们在在不修改源代码的前提下实现功能增强,底层实现基于动态代理或者CGLIB
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
定义注解
package com.yungua.springboot.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodExporter {
}
定义切面
package com.yungua.springboot.aspect;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
// 当前对象是一个切面
@Aspect
// 允许在SpringIOC对当前对象实例化并管理
@Component
@Slf4j
public class MethodExporterAspect {
// 任何增加了@MethodExporter自定义注解的方法都将在执行前执行该切面方法
// @Around环绕通知,可以控制方法入参、执行、返回结果等各方面细节
@Around("@annotation(com.yungua.springboot.anno.MethodExporter)")
public Object methodExporter(ProceedingJoinPoint joinPoint) throws Throwable {
long st = System.currentTimeMillis();
// 执行目标方法,获取返回值
Object proceed = joinPoint.proceed();
long et = System.currentTimeMillis();
ObjectMapper mapper = new ObjectMapper();
// 将入参JSON序列化
String jsonParam = mapper.writeValueAsString(joinPoint.getArgs());
// 将返回结果JSON序列化
String jsonResult = null;
if (proceed != null) {
jsonResult = mapper.writeValueAsString(proceed);
}
log.info("exec info\ntarget:{}.{}\nexecution:{}ms\nparameter:{}\nresult:{}"
, joinPoint.getTarget().getClass().getSimpleName()
, joinPoint.getSignature().getName()
,(et - st)
, jsonParam
, jsonResult
);
return proceed;
}
}
测试
@RestController
@RequestMapping("home")
public class HomeController {
@MethodExporter
@GetMapping
public String index(){
ThreadUtil.sleep(2000);
return RandomUtil.randomString(10);
}
}
结果
2023-03-26 15:53:10.183 INFO 9452 --- [nio-8080-exec-1] c.y.s.aspect.MethodExporterAspect : exec info
target:HomeController.index
execution:2011ms
parameter:[]
result:"rx3w1hengr"
标签:java,String,Greeting,代理,AOP,import,public,greeting
From: https://www.cnblogs.com/dylmys/p/17258746.html