将AOP融入到Spring,依然是使用Bean后置处理器,最关键的类DefaultAdvisorAutoProxyCreator
一、通知
通知是对方法拦截器逻辑的细化,本次我们只实现前置通知
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
新建前置通知接口BeforeAdvice,继承aop_alliance的Advice接口,做统一包装
public interface BeforeAdvice extends Advice {
}
新建方法前置通知接口MethodBeforeAdvice,继承BeforeAdvice
- 定义一个before方法
- 由实现类提供before的具体逻辑
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, Object target) throws Throwable;
}
新建顾问Advisor接口,顾名思义,顾问就是用来提供建议的
- 提供一个获取建议的方法,
public interface Advisor {
Advice getAdvice();
}
新建切点顾问子接口,继承顾问
- 顾问需要关联具体的切点
- 提供一个获取切点的方法
public interface PointcutAdvisor extends Advisor{
/**
* Get the Pointcut that drives this advisor.
*/
Pointcut getPointcut();
}
新建一个实现类AspectJExpressionPointcutAdvisor,融合上述所有的概念
- 切点
- 通知
- 表达式
public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor {
// 切点
private AspectJExpressionPointcut pointcut;
// 通知
private Advice advice;
// 表达式
private String expression;
public void setExpression(String expression){
this.expression = expression;
}
@Override
public Pointcut getPointcut() {
if (null == pointcut) {
pointcut = new AspectJExpressionPointcut(expression);
}
return pointcut;
}
@Override
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
}
新建方法前置通知拦截器,实现aop_alliance提供的MethodInterceptor接口
- 目的是为了将方法拦截器进行分类
- 专注于处理前置增强逻辑
public class MethodBeforeAdviceInterceptor implements MethodInterceptor {
private MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor() {
}
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
二、融入Spring
修改包装类AdvisedSupport
- 新增proxyTargetClass属性,判断是否使用cglib,默认false
@Data
public class AdvisedSupport {
// 是否开启cglib,默认false
private boolean proxyTargetClass = false;
// 目标对象
private TargetSource targetSource;
// 通知
private MethodInterceptor methodInterceptor;
// 方法匹配器
private MethodMatcher methodMatcher;
}
新建代理工厂
- 工厂模式
- 用于获取AopProxy
public class ProxyFactory {
private final AdvisedSupport advisedSupport;
public ProxyFactory(AdvisedSupport advisedSupport) {
this.advisedSupport = advisedSupport;
}
public Object getProxy() {
return createAopProxy().getProxy();
}
private AopProxy createAopProxy() {
if (advisedSupport.isProxyTargetClass()) {
return new Cglib2AopProxy(advisedSupport);
}
return new JdkDynamicAopProxy(advisedSupport);
}
}
新建Bean后置处理器子接口InstantiationAwareBeanPostProcessor,继承于BeanPostProcessor
- 扩展一个新方法,在Bean实例化前执行
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor{
/**
* 在 Bean 对象执行实例化方法之前,执行此方法
* @param beanClass
* @param beanName
* @return
*/
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName);
}
新建融入Spring的关键类DefaultAdvisorAutoProxyCreator
- 实现InstantiationAwareBeanPostProcessor
- 实现BeanFactoryAware
public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
private DefaultListableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = (DefaultListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 基础设施的Bean不用被代理
if (isInfrastructureClass(beanClass)) return null;
Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
ClassFilter classFilter = advisor.getPointcut().getClassFilter();
if (!classFilter.matches(beanClass)) continue;
AdvisedSupport advisedSupport = new AdvisedSupport();
TargetSource targetSource = null;
try {
targetSource = new TargetSource(beanClass.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
}
advisedSupport.setTargetSource(targetSource);
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());
advisedSupport.setProxyTargetClass(false);
return new ProxyFactory(advisedSupport).getProxy();
}
return null;
}
/**
* 判断一个Bean是否是基础设施类
* @param beanClass
* @return
*/
private boolean isInfrastructureClass(Class<?> beanClass) {
return Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass);
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
重写createBean方法
- 暂时简化处理,直接判断是否返回代理对象
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) {
Object bean = null;
// 判断是否需要返回代理Bean对象
bean = resolveBeforeInstantiation(beanName, beanDefinition);
if (null != bean) {
return bean;
}
// 实例化,包括构造函数注入
bean = doCreateBean(beanName, beanDefinition, args);
// 依赖注入
populateBean(beanName, bean, beanDefinition);
// 初始化
bean = initializeBean(beanName, bean, beanDefinition);
// 注册实现了 DisposableBean 接口的 Bean 对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
// 是否加入单例池
if (beanDefinition.isSingleton()) {
addSingleton(beanName, bean);
}
return bean;
}
protected Object resolveBeforeInstantiation(String beanName, BeanDefinition beanDefinition) {
Object bean = applyBeanPostProcessorsBeforeInstantiation(beanDefinition.getBeanClass(), beanName);
if (null != bean) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
Object result = ((InstantiationAwareBeanPostProcessor) beanPostProcessor).postProcessBeforeInstantiation(beanClass, beanName);
if (null != result) return result;
}
}
return null;
}
三、测试
自定义方法拦截器
public class CatBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("猫前置增强:" + method.getName());
}
}
创建前置通知
- 手动组装到Spring的前置方法拦截器
public class CatBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("猫前置增强:" + method.getName());
}
}
编写spring.xml,主要就是cat,DefaultAdvisorAutoProxyCreator,pointcutAdvisor(顾问,以及需要的方法拦截器)
- cat,被拦截的类
- Aop核心类,DefaultAdvisorAutoProxyCreator放进容器
- 通知,CatBeforeAdvice
- 方法拦截器,catInterceptor
- 顾问,pointcutAdvisor
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="cat" class="cn.shopifymall.springframework.test.bean.Cat"/>
<bean class="cn.shopifymall.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean id="catBeforeAdvice" class="cn.shopifymall.springframework.test.bean.CatBeforeAdvice"/>
<bean id="catInterceptor" class="cn.shopifymall.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor">
<property name="advice" ref="catBeforeAdvice"/>
</bean>
<bean id="pointcutAdvisor" class="cn.shopifymall.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="expression" value="execution(* cn.shopifymall.springframework.test.bean.Eat.*(..))"/>
<property name="advice" ref="catInterceptor"/>
</bean>
</beans>
在refresh()方法里面,首先会加载DefaultAdvisorAutoProxyCreator(BeanPostProcessor),然后实例化Cat
测试类
@Test
public void test_auto_aop() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springTest.xml");
Eat cat = (Eat) applicationContext.getBean("cat");
System.out.println("测试结果:" + cat.eatFish("大马哈鱼"));
}
结果
猫前置增强:eatFish
20:18:30.957 [main] INFO cn.shopifymall.springframework.test.bean.Cat - 猫正在吃鱼
测试结果:吃了一条大马哈鱼
断点查看,Cat是代理对象