Spring-AOP 深度剖析
www.tomblog.club 我的博客欢迎大家访问
一、AOP的应用场景
1.SpringBoot整合AOP,异步记录日志.
1.1 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1.2 编写自定义注解
import java.lang.annotation.*;
/**
* @author Administrator
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}
1.3 编写切面类记录日志
import lombok.Data;
/**
* @author Administrator
*/
@Data
public class SysLogEntity {
private String className;
private String methodName;
private String params;
private Long exeuTime;
private String remark;
private String createDate;
}
import com.mayikt.springsource.annotaion.SysLog;
import com.mayikt.springsource.model.entity.SysLogEntity;
import com.mayikt.springsource.service.SysLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 日志切面
*
* @author zx
* @date 2022年01月15日 21:48
*/
//@EnableAspectJAutoProxy
@Aspect
@Component
@Slf4j
public class LogAop {
@Autowired
private SysLogService sysLogService;
/**
* 这里我们使用注解的形式
* 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
* 切点表达式: execution(...)
*/
@Pointcut("@annotation(com.mayikt.springsource.annotaion.SysLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
Object result = point.proceed();
long time = System.currentTimeMillis() - beginTime;
try {
//实现保存日志逻辑
saveLog(point, time);
} catch (Exception e) {
}
log.info("响应结果:{}", result);
return result;
}
private void saveLog(ProceedingJoinPoint joinPoint, long time) {
// 获取方法的关键信息,类,包
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLogEntity sysLogEntity = new SysLogEntity();
sysLogEntity.setExeuTime(time);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
sysLogEntity.setCreateDate(dateFormat.format(new Date()));
SysLog sysLog = method.getAnnotation(SysLog.class);
if (sysLog != null) {
//注解上的描述
sysLogEntity.setRemark(sysLog.value());
}
//请求的 类名、方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLogEntity.setClassName(className);
sysLogEntity.setMethodName(methodName);
//请求的参数
Object[] args = joinPoint.getArgs();
try {
List<String> list = new ArrayList<String>();
for (Object o : args) {
list.add(o.toString());
}
sysLogEntity.setParams(list.toString());
} catch (Exception e) {
}
//改成异步(MQ)
sysLogService.save(sysLogEntity);
}
}
1.4 异步保存日志
import com.mayikt.springsource.model.entity.SysLogEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class SysLogService {
@Async
public boolean save(SysLogEntity sysLogEntity){
// 这里就不做具体实现了
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("threadName:{},sysLogEntity=====>{}",Thread.currentThread().getName(),sysLogEntity.toString());
return true;
}
}
1.5 开启异步功能
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class SpringSourceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringSourceApplication.class, args);
}
}
2. AOP 5大通知
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.14</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
<scope>compile</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-aop</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
package com.mayikt.springsource.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
/**
* 日志切面
*
* @author zx
* @date 2022年01月16日 8:42
*/
@Component
@Aspect
@EnableAspectJAutoProxy
public class LogAop {
///**
// * 这里我们使用注解的形式
// * 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
// * 切点表达式: execution(...)
// */
//@Pointcut("@annotation(com.mayikt.springsource.annotaion.SysLog)")
//public void logPointCut() {
//}
@Pointcut("execution (* com.mayikt.springsource..*.*(..))")
public void loginAop() {
}
@Before("loginAop()")
public void doBefore(JoinPoint joinPoint) {
System.out.println(">>>>>>>前置通知<<<<<<<<<<< ");
}
@After("loginAop()")
public void doAfter(JoinPoint joinPoint) {
System.out.println(">>>>>>>>后置通知<<<<<<<<<");
}
@Around("loginAop()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println(">>>>环绕通知之前执行...>>>>>>");
Object proceed = joinPoint.proceed();// 执行目标方案
System.out.println(">>>>环绕通知之后执行...>>>>>>");
return proceed;
}
/**
* 运行通知
*/
@AfterReturning("loginAop()")
public void afterReturning(JoinPoint joinPoint) {
System.out.println("运行通知执行.....");
}
/**
* 异常通知
*/
@AfterThrowing("loginAop()")
public void afterThrowing(JoinPoint joinPoint) {
System.out.println(">>>>>异常通知");
}
}
import java.lang.annotation.*;
/**
* @author Administrator
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}
2.1 通知执行顺序
2.1.1 没有抛异常
import com.sun.istack.internal.NotNull;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制类
*
* @author zx
* @date 2022年01月16日 8:29
*/
@RestController
public class UserController {
/**
* NotNull 表示一个提示警告程序员注意空指针
*
* @param username 用户名称
* @return username 用户名称
*/
@GetMapping("/getUserInfo")
public String getUserInfo(@NotNull String username) {
System.out.println("username:"+username);
return username;
}
打印结果:
>>>>环绕通知之前执行...>>>>>>
>>>>>>>前置通知<<<<<<<<<<<
username:tom
运行通知执行.....
>>>>>>>>后置通知<<<<<<<<<
>>>>环绕通知之后执行...>>>>>>
2.1.2 抛出异常
import com.sun.istack.internal.NotNull;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制类
*
* @author zx
* @date 2022年01月16日 8:29
*/
@RestController
public class UserController {
/**
* NotNull 表示一个提示警告程序员注意空指针
*
* @param username 用户名称
* @return username 用户名称
*/
@GetMapping("/getUserInfo")
public String getUserInfo(@NotNull String username) {
System.out.println("username:"+username);
int i = 1/0;
return username;
}
}
打印结果:
>>>>环绕通知之前执行...>>>>>>
>>>>>>>前置通知<<<<<<<<<<<
username:tom2
>>>>>异常通知
>>>>>>>>后置通知<<<<<<<<<
java.lang.ArithmeticException: / by zero
3.责任链设计模式
责任链模式怎么使用呢?
- 一个接口或者抽象类
- 每个对象差异化处理
- 对象链(数组)初始化(连起来)
3.1 一个接口或者抽象类
这个接口或者抽象类,需要:
- 有一个指向责任下一个对象的属性
- 一个设置下一个对象的set方法
- 给子类对象差异化实现的方法(如以下代码的doFilter方法)
public abstract class AbstractHandler {
//责任链中的下一个对象
private AbstractHandler nextHandler;
/**
* 责任链的下一个对象
*/
public void setNextHandler(AbstractHandler nextHandler){
this.nextHandler = nextHandler;
}
/**
* 具体参数拦截逻辑,给子类去实现
*/
public void filter(Request request, Response response) {
doFilter(request, response);
if (getNextHandler() != null) {
getNextHandler().filter(request, response);
}
}
public AbstractHandler getNextHandler() {
return nextHandler;
}
abstract void doFilter(Request filterRequest, Response response);
}
3.2 每个对象差异化处理
责任链上,每个对象的差异化处理,如本小节的业务场景,就有参数校验对象、安全校验对象、黑名单校验对象、规则拦截对象
import com.mayikt.projecttest.responsibilitychain.AbstractHandler;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 黑名单校验对象
*/
@Component
@Order(3) //校验顺序排第3
public class CheckBlackFilterObject extends AbstractHandler {
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response) {
//invoke black list check
System.out.println("校验黑名单");
}
}
import com.mayikt.projecttest.responsibilitychain.AbstractHandler;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 参数校验对象
**/
@Component
@Order(1) //顺序排第1,最先校验
public class CheckParamFilterObject extends AbstractHandler {
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response) {
System.out.println("非空参数检查");
}
}
import com.mayikt.projecttest.responsibilitychain.AbstractHandler;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 规则拦截对象
*/
@Component
@Order(4) //校验顺序排第4
public class CheckRuleFilterObject extends AbstractHandler {
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response) {
//check rule
System.out.println("check rule");
}
}
import com.mayikt.projecttest.responsibilitychain.AbstractHandler;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 安全校验对象
*/
@Component
@Order(2) //校验顺序排第2
public class CheckSecurityFilterObject extends AbstractHandler {
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response) {
//invoke Security check
System.out.println("安全调用校验");
}
}
3.3 对象链连起来(初始化)&& 使用
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Component("ChainPatternDemo")
public class ChainPatternDemo {
//自动注入各个责任链的对象
@Autowired
private List<AbstractHandler> abstractHandleList;
private AbstractHandler abstractHandler;
//spring注入后自动执行,责任链的对象连接起来
@PostConstruct
public void initializeChainFilter(){
for(int i = 0;i<abstractHandleList.size();i++){
if(i == 0){
abstractHandler = abstractHandleList.get(0);
}else{
AbstractHandler currentHander = abstractHandleList.get(i - 1);
AbstractHandler nextHander = abstractHandleList.get(i);
currentHander.setNextHandler(nextHander);
}
}
}
//直接调用这个方法使用
public void exec(HttpServletRequest request, HttpServletResponse response) {
abstractHandler.filter(request, response);
}
public AbstractHandler getAbstractHandler() {
return abstractHandler;
}
public void setAbstractHandler(AbstractHandler abstractHandler) {
this.abstractHandler = abstractHandler;
}
}
3.4 责任链案例
Api接口限流→黑名单拦截→用户会话→参数过滤
3.4.1 GatewayHandler抽象角色
public abstract class GatewayHandler {
protected GatewayHandler nextGatewayHandler;
/**
* 处理业务逻辑
*
* @return true 表示继续执行 false表示不继续执行..
*/
public abstract void service();
public void setHandler(GatewayHandler gatewayHandler) {
this.nextGatewayHandler = gatewayHandler;
}
protected void nextService(){
if(nextGatewayHandler!=null){
nextGatewayHandler.service();;
}
}
}
3.4.2 具体Handler实现
@Component
public class CurrentLimitHandler extends GatewayHandler {
@Override
public void service() {
System.out.println("第一关网关限流判断....");
nextService();
}
}
@Component
public class ConversationHandler extends GatewayHandler {
@Override
public void service() {
System.out.println("第三关用户会话拦截判断....");
nextService();
}
}
@Component
public class BlacklistHandler extends GatewayHandler {
@Override
public void service() {
System.out.println("第二关黑名单拦截判断....");
nextService();
}
}
@Component
public class ConversationHandler extends GatewayHandler {
@Override
public void service() {
System.out.println("第三关用户会话拦截判断....");
nextService();
}
}
3.4.3 构建链上关系
public class FactoryHandler {
public static GatewayHandler getGatewayHandler() {
GatewayHandler gatewayHandler1 = new CurrentLimitHandler();
GatewayHandler gatewayHandler2 = new BlacklistHandler();
gatewayHandler1.setHandler(gatewayHandler2);
GatewayHandler gatewayHandler3 = new ConversationHandler();
gatewayHandler2.setHandler(gatewayHandler3);
return gatewayHandler1;
}
}
4.代理模式
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* jdk动态代理
*
* @author zx
* @date 2022年01月16日 11:38
*/
public class JdkDynamicProxy<T> implements InvocationHandler {
private T target;
public JdkDynamicProxy(T target) {
this.target = target;
}
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行目标方法之前");
Object invoke = method.invoke(target, args);
System.out.println("执行目标方法之后");
return invoke;
}
}
/**
* @author zx
* @date 2022年01月16日 11:43
*/
public interface UserService {
String getUserInfo();
}
import com.mayikt.springsource.service.UserService;
/**
* @author zx
* @date 2022年01月16日 11:44
*/
public class UserServiceImpl implements UserService {
@Override
public String getUserInfo() {
return "tom is java paramgrame";
}
}
import com.mayikt.springsource.service.UserService;
import com.mayikt.springsource.config.MyConfig;
import com.mayikt.springsource.service.imple.UserServiceImpl;
import com.mayikt.springsource.proxy.JdkDynamicProxy;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author zx
* @date 2022年01月16日 9:33
*/
public class MainTest {
public static void main(String[] args) {
JdkDynamicProxy<UserService> userServiceJdkDynamicProxy = new JdkDynamicProxy<>(new UserServiceImpl());
UserService proxy = userServiceJdkDynamicProxy.getProxy();
String userInfo = proxy.getUserInfo();
System.out.println(userInfo);
}
}
4.1 JDK代理的另一种写法
多个接口实现代理
package com.mayikt.designpattern.structurepattern.jdkproxy;
public interface ManTikTok {
void tiktok();
}
package com.mayikt.designpattern.structurepattern.jdkproxy;
public interface SellTikTok {
void sell();
}
package com.mayikt.designpattern.structurepattern.jdkproxy;
//
public class LeiTikTok implements ManTikTok,SellTikTok {
// @Override
public void tiktok() {
System.out.println("雷丰阳,tiktok.... ");
}
@Override
public void sell() {
System.out.println("雷丰阳,只要666,赶紧来包...");
}
public void haha(){
System.out.println("hahaha ,......");
}
}
public class JdkProxy {
/**
* 被代理类 ,即目标类
* 目标类需要实现公共的接口
*/
private Object target;
public JdkProxy(Object target) {
this.target = target;
}
/**
* 获取代理对象
*/
public <T> T getProxyObj() {
InvocationHandler handler = (proxy, method, args) -> {
System.out.println("1.方法前执行~~~~~");
Object invoke = method.invoke(target, args);
if (invoke != null) {
System.out.println(invoke);
}
System.out.println("2.方法后执行~~~~~~");
return invoke;
};
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), handler);
}
}
public class MainTestProxy {
public static void main(String[] args) {
ManTikTok proxyObj = new JdkProxy(new LeiTikTok()).getProxyObj();
proxyObj.tiktok();
}
}
4.2 实现Mapper代理-lambda写法
import com.example.proxy.anotaion.Select;
public interface IUserDao {
@Select("select * from mayikt_type where id = #{uId}")
String queryUserInfo(String uId);
}
import com.example.proxy.anotaion.Select;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* 对代理类的定义
* @param <T>
*/
public class MapperFactoryBean<T> implements FactoryBean<T> {
private Logger logger = LoggerFactory.getLogger(MapperFactoryBean.class);
private Class<T> mapperInterface;
public MapperFactoryBean(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
@Override
public T getObject() throws Exception {
InvocationHandler handler = (proxy, method, args) -> {
Select select = method.getAnnotation(Select.class);
logger.info("SQL:{}", select.value().replace("#{uId}", args[0].toString()));
return args[0] + ",沉淀、分享、成⻓,让⾃⼰和他 ⼈都能有所收获!";
};
return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]
{mapperInterface}, handler);
}
@Override
public Class<?> getObjectType() {
return mapperInterface;
}
@Override
public boolean isSingleton() {
return true;
}
}
import com.example.proxy.mapper.IUserDao;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
/**
* 这⾥我们将代理的bean交给spring容器管理,也就可以⾮常⽅便让我们可以获取到代理的bean。这部分是spring中关于⼀个bean注册过程的源码。
* GenericBeanDefinition ,⽤于定义⼀个bean的基本信息 setBeanClass(MapperFactoryBean.class);
* , 也包括可以透传给构造函数信息 addGenericArgumentValue(IUserDao.class);
* 最后使⽤ BeanDefinitionReaderUtils.registerBeanDefinition ,进⾏bean的注册,也就
* 是注册到 DefaultListableBeanFactory 中。
*/
public class RegisterBeanFactory implements BeanDefinitionRegistryPostProcessor/*beanfactory后置处理器*/ {
/**
* 注册bean定义信息注入到容器中
* @param registry
* @throws BeansException
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MapperFactoryBean.class);
beanDefinition.setScope("singleton");
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(IUserDao.class);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, "userDao");
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-autowire="byName">
<bean id="userDao"
class=" com.example.proxy.factory.RegisterBeanFactory"/>
</beans>
@SpringBootTest
class MayiktProxyDemoApplicationTests {
Logger logger = LoggerFactory.getLogger(MayiktProxyDemoApplicationTests.class);
@Test
void contextLoads() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
IUserDao userDao = beanFactory.getBean("userDao", IUserDao.class);
String res = userDao.queryUserInfo("1");
logger.info("测试结果:{}", res);
}
}
SpringAop 中使用jdk代理和cglib代理, 被代理类实现抽象主题接口实现接口 采用的是jdk代理; 被代理类继承抽象的主题角色采用cglib代理
4.3 对接口方法代理
在一些rpc框架中,客户端只需要关注接口的的调用,而具体的远程请求则由框架内部实现。
public interface OrderInterface {
/**
* 生成一张新订单
*/
void addOrder(String name);
}
import com.example.proxy.util.HttpClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SimpleRpcFrame {
Logger logger = LoggerFactory.getLogger(SimpleRpcFrame.class);
/**
* 创建一个远程请求代理对象
*/
public static <T> T getRemoteProxy(Class<T> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(),
new Class<?>[]{service},
new RpcHandler(service));
}
/**
* 处理具体远程调用的类
*/
static class RpcHandler implements InvocationHandler {
Logger logger = LoggerFactory.getLogger(RpcHandler.class);
private Class service;
public RpcHandler(Class service) {
this.service = service;
}
//真正调用远程接口
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 根据接口名和方法名,发起一次特定的网络请求,获取数据
*/
//Object result = RemoteCallUtility.request(service.getName(), method.getName(), args);
String name = service.getName();
String name1 = method.getName();
Object result = null;
//logger.info("参数args:{}",args);
//
//JSONArray jsonArray = JSON.parseArray(args.toString());
//logger.info("转换后的jsonArray:{}",jsonArray);
result = HttpClientUtil.doPost("http://www.baidu.com", null);
return result;
}
}
}
public class RpcInvoker {
public void invoke(String name) {
OrderInterface order = SimpleRpcFrame.getRemoteProxy(OrderInterface.class);
order.addOrder(name);
}
}
@Test
void proxyInterface(){
RpcInvoker rpcInvoker = new RpcInvoker();
rpcInvoker.invoke("zhongxu");
}
二、@EnableAspectJAutoProxy源码分析
2.1 创建代理对象
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
根据给定的EnableAspectJAutoProxy注解,根据当前的BeanDefinitionRegistry注册AnnotationAwareAspectJAutoProxyCreator
AbstractAutoProxyCreator
的后置通知中创建代理类. 最终实现BeanPostProcessor
后置处理,Bean初始化之后调用,最终放到一级缓存中。[结合Bean创建生命周期,没有循环依赖,在初始化之后会调用后置处理器]
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary(bean, beanName, cacheKey);
如有必要,包装给定的bean,即如果它有资格被代理
Necessary 必要的
wrap 包
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
通过代理工厂创建代理对象.其中封装了切面调用链路封装Advisor
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
if (Proxy.isProxyClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
DefaultAopProxyFactory.createAopProxy()
创建代理对象
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
2.2 如何判断类实现接口
DefaultAopProxyFactory.createAopProxy()
创建代理对象 中的判断类是否实现接口hasNoUserSuppliedProxyInterfaces(config))
确定提供的AdvisedSupport是否仅指定了SpringProxy接口(或根本没有指定代理接口)
/**
* Determine whether the supplied {@link AdvisedSupport} has only the
* {@link org.springframework.aop.SpringProxy} interface specified
* (or no proxy interfaces specified at all).
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
三、AOP底层调用链路分析
递归责任链调用方式