Spring--05--AOP原生实现方式

概述

Spring 整合AspectJ框架实现AOP只是Spring框架中AOP的一种实现方式,此方式相对比较简单,实现方便。但此方式底层还是要转换为Spring原生AOP的实现,Spring AOP原生方式实现的核心有三大部分构成,分别是:

  • JDK代理。
  • CGLIB代理
  • org.aopalliance包下的拦截体系

架构分析

在这里插入图片描述
其中DefaultAdvisorAutoProxyCreator这个类功能更为强大,这个类的奇妙之处是他实现BeanPostProcessor接口,当ApplicationContext读取所有的Bean配置信息后,这个类将扫描上下文,寻找所有的Advisor对象(一个Advisor由切入点和通知组成),将这些Advisor应用到所有符合切入点的Bean中。

实际案例

项目结构

在这里插入图片描述

PjApplication主启动类

主启动类 配置 DefaultAdvisorAutoProxyCreator对象 ,一般是配置在配置类上,这里为了简化代码,放在主启动类上.

@SpringBootApplication
public class PjApplication {
	
	@Bean 
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		//此对象会在容器启动时扫描Advisor对象,然后基于切入点为目标对象创建代理对象
		//然后再执行切入点方法时,自动执行Advice对象通知方法
		return new DefaultAdvisorAutoProxyCreator();
	}
	public static void main(String[] args) {
		SpringApplication.run(CgbSourceAop01Application.class, args);
	}
}

@Bean注解应用于配置类中(使用了@Configuration修饰)
@Bean描述的方法其返回值会交给spring管理,spring管理这个bean默认bean名字为方法名

  1. DefaultAdvisorAutoProxyCreator对象会在容器启动时扫描Advisor对象
  2. 然后基于切入点为目标对象创建代理对象
  3. 然后再执行切入点方法时,自动执行Advice对象通知方法

RequiredLog 注解

/**借助此注解描述切入点方法*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiredLog {

}

service 接口

public interface MailService {
	  boolean sendMsg(String msg);
}

MailServiceImpl 目标方法实现类

@Service
public class MailServiceImpl implements MailService {
	
	@RequiredLog //希望这个注解描述的方法为一个切入点方法(目标方法)
	@Override
	public boolean sendMsg(String msg) {
		//System.out.println("start:"+System.currentTimeMillis());
		System.out.println("send "+msg);
		//System.out.println("end:"+System.currentTimeMillis());
		return true;
	}
}

LogAdvice 通知方法

继承 MethodInterceptor接口

/**
 *  日志通知对象
 */
public class LogAdvice implements MethodInterceptor {
	

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("start:"+System.currentTimeMillis());
		Object result=invocation.proceed();//执行目标方法
		System.out.println("end:"+System.currentTimeMillis());
		return result;
	}
}
  • 切入点对应的目标方法执行之前执行,可以在目标方法执行之前和之后做点拓展业务
  • invocation连接点对象(封装了要执行的目标方法信息,可以通过反射调用目标方法)

LogAdvisor 顾问 (内部注册通知,判断切入点方法)

实现啦 Advisor接口

Spring容器在启动时会基于BeanPostProcessor找到所有的Advisor对象(顾问),并基于Advisor对象中切入点的描述为目标对象创建代理对象.当执行目标方法时会执行Advisor对象关联通知.

@Component
public class LogAdvisor extends StaticMethodMatcherPointcutAdvisor {
	private static final long serialVersionUID = -3987392064269894257L;
	public LogAdvisor() {
		//在advisor内部注册一个日志通知
		setAdvice(new LogAdvice());
	}
    /**
     * 
     * matches方法用于判定方法参数中的method是否为一个切入点方法,当它的返回值
     * 	为true时,表示参数中的method对象为一个切入点方法.
     * @param method 对应了目标方法对象(可能是目标方法所在类的父类方法对象)
     * @param targetClass 代表目标对象类型
     */
	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		try {
		    Method targetMethod=
		    targetClass.getMethod(method.getName(), method.getParameterTypes());
		    //检测目标方法上是否有requiredLog注解
		    return targetMethod.isAnnotationPresent(RequiredLog.class);
		}catch(Exception e) {
			return false;
		}
	}

}

测试 Tests

@SpringBootTest
public class MailServiceTests {

	@Autowired
	private MailService mailService;
	@Test
	void testSendMsg() {
		mailService.sendMsg("hello cgb2006");
	}
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值