提交 0b2c279b 编写于 作者: 希川's avatar 希川

<feat>: 循环依赖问题 part two

上级 f30bb862
......@@ -30,4 +30,12 @@ public class MethodBeforeAdviceInterceptor implements MethodInterceptor {
this.advice.before(invocation.getMethod(), invocation.getArguments(), invocation.getThis());
return invocation.proceed();
}
public MethodBeforeAdvice getAdvice() {
return advice;
}
public void setAdvice(MethodBeforeAdvice advice) {
this.advice = advice;
}
}
......@@ -14,6 +14,9 @@ import org.aopalliance.intercept.MethodInterceptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* DefaultAdvisorAutoProxyCreator
......@@ -26,6 +29,8 @@ public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPos
private DefaultListableBeanFactory beanFactory;
private final Set<Object> earlyProxyReferences = Collections.synchronizedSet(new HashSet<>());
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (DefaultListableBeanFactory) beanFactory;
......@@ -38,10 +43,45 @@ public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPos
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (isInfrastructureClass(bean.getClass())) return bean;
if (!earlyProxyReferences.contains(beanName)) {
return wrapIfNecessary(bean, beanName);
}
return bean;
}
Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* 检测/感知 bean 是否是切点 <p>按需拦截
*/
private boolean isInfrastructureClass(Class<?> beanClass) {
return Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass);
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return pvs;
}
@Override
public Object getEarlyBeanReference(Object exposedObject, String beanName) {
earlyProxyReferences.add(beanName);
return wrapIfNecessary(exposedObject, beanName);
}
protected Object wrapIfNecessary(Object bean, String beanName) {
if (isInfrastructureClass(bean.getClass())) {
return bean;
}
Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
ClassFilter classFilter = advisor.getPointcut().getClassFilter();
// 过滤匹配类
......@@ -57,34 +97,15 @@ public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPos
// 设置匹配器
advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());
// 设置选择使用的代理方法
advisedSupport.setProxyTargetClass(false);
advisedSupport.setProxyTargetClass(true);
// 返回代理对象
return new ProxyFactory(advisedSupport).getProxy();
}
return bean;
}
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* 检测/感知 bean 是否是切点 <p>按需拦截
*/
private boolean isInfrastructureClass(Class<?> beanClass) {
return Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass);
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return pvs;
}
}
......@@ -33,4 +33,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* @throws BeansException
*/
PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException;
default Object getEarlyBeanReference(Object exposedObject, String beanName){
return exposedObject;
}
}
......@@ -34,7 +34,7 @@ public abstract class AbstractAutowiredCapableBeanFactory extends AbstractBeanFa
}
// 实例化后判断
boolean continueWithPropertyPopulation = applyBeanPostProcessorsAfterInitialization(beanName, bean);
boolean continueWithPropertyPopulation = applyBeanPostProcessorsAfterInstantiation(beanName, bean);
if (!continueWithPropertyPopulation) {
return bean;
}
......@@ -62,14 +62,31 @@ public abstract class AbstractAutowiredCapableBeanFactory extends AbstractBeanFa
return exposedObject;
}
private boolean applyBeanPostProcessorsAfterInitialization(String beanName, Object bean) {
// TODO
return false;
private boolean applyBeanPostProcessorsAfterInstantiation(String beanName, Object bean) {
boolean continueWithPropertyPopulation = true;
for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor instantiationAwareBeanPostProcessor = (InstantiationAwareBeanPostProcessor) beanPostProcessor;
if (!instantiationAwareBeanPostProcessor.postProcessAfterInstantiation(bean, beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
return continueWithPropertyPopulation;
}
protected Object getEarlyBeanReference(String beanName, BeanDefinition beanDefinition, Object finalBean) {
// todo
return null;
protected Object getEarlyBeanReference(String beanName, BeanDefinition beanDefinition, Object bean) {
Object exposedObject = bean;
for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
exposedObject = ((InstantiationAwareBeanPostProcessor) beanPostProcessor).getEarlyBeanReference(exposedObject, beanName);
if (null == exposedObject)
return exposedObject;
}
}
return exposedObject;
}
@Override
......
......@@ -40,7 +40,7 @@ public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
Object singletonObject = singletonObjects.get(beanName);
if (null == singletonObject) {
singletonObject = earlySingletonObjects.get(beanName);
// 判断耳机缓存中是否有对象,这个对象就是代理对象,因为只有代理对象才会放到三级缓存中
// 判断二级缓存中是否有对象,这个对象就是代理对象,因为只有代理对象才会放到三级缓存中
if (null == singletonObject) {
ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
......
......@@ -10,6 +10,8 @@ import cn.noexception.test.bean.IUserService;
import cn.noexception.test.bean.UserService;
import cn.noexception.test.bean.UserServiceInterceptor;
import cn.noexception.test.event.CustomEvent;
import cn.noexception.test.loop.Husband;
import cn.noexception.test.loop.Wife;
import org.junit.Test;
public class ApiRunner {
......@@ -79,4 +81,13 @@ public class ApiRunner {
System.out.println("测试结果:"+userService.queryUserInfo());
}
@Test
public void test_circular(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-loop.xml");
Husband husband = applicationContext.getBean("husband", Husband.class);
Wife wife = applicationContext.getBean("wife", Wife.class);
System.out.println(husband.queryWife());
System.out.println(wife.queryHusband());
}
}
package cn.noexception.test.loop;
/**
* Husband
*
* @author 吕滔
* @Date 2021/11/17 15:10
*/
public class Husband {
private Wife wife;
public String queryWife(){
return "Husband.wife";
}
public Wife getWife() {
return wife;
}
public void setWife(Wife wife) {
this.wife = wife;
}
}
package cn.noexception.test.loop;
import cn.noexception.container.factory.FactoryBean;
import java.lang.reflect.Proxy;
/**
* HusbandMother
*
* @author 吕滔
* @Date 2021/11/17 15:12
*/
public class HusbandMother implements FactoryBean<IMother> {
@Override
public IMother getObject() throws Exception {
return (IMother) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{IMother.class}, ((proxy, method, args) -> "婚后媳妇妈妈的职责被婆婆代理了!"+method.getName()));
}
@Override
public Class<?> getObjectType() {
return IMother.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
package cn.noexception.test.loop;
/**
* IMother
*
* @author 吕滔
* @Date 2021/11/17 15:11
*/
public interface IMother {
String callMother();
}
package cn.noexception.test.loop;
import cn.noexception.container.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* SpouseAdvice
*
* @author 吕滔
* @Date 2021/11/17 15:15
*/
public class SpouseAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("关怀小两口:" + method);
}
}
package cn.noexception.test.loop;
/**
* Wife
*
* @author 吕滔
* @Date 2021/11/17 15:10
*/
public class Wife {
private Husband husband;
private IMother mother;
public String queryHusband(){
return "Wife.husband、Mother.callMother: "+mother.callMother();
}
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
public IMother getMother() {
return mother;
}
public void setMother(IMother mother) {
this.mother = mother;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context">
<bean id="husband" class="cn.noexception.test.loop.Husband">
<property name="wife" ref="wife"/>
</bean>
<bean id="wife" class="cn.noexception.test.loop.Wife">
<property name="husband" ref="husband"/>
<property name="mother" ref="husbandMother"/>
</bean>
<bean id="husbandMother" class="cn.noexception.test.loop.HusbandMother"/>
<!--验证三级缓存-->
<bean class="cn.noexception.container.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean id="beforeAdvice" class="cn.noexception.test.loop.SpouseAdvice"/>
<bean id="methodInterceptor" class="cn.noexception.container.aop.framework.adapter.MethodBeforeAdviceInterceptor">
<property name="advice" ref="beforeAdvice"/>
</bean>
<bean id="pointcutAdvisor" class="cn.noexception.container.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="expression" value="execution(* cn.noexception.test.loop.Wife.*(..))"/>
<property name="advice" ref="methodInterceptor"/>
</bean>
</beans>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册