diff --git a/src/main/java/org/m1a2st/aop/AdvisedSupport.java b/src/main/java/org/m1a2st/aop/AdvisedSupport.java index e22ddeb..ea3b554 100644 --- a/src/main/java/org/m1a2st/aop/AdvisedSupport.java +++ b/src/main/java/org/m1a2st/aop/AdvisedSupport.java @@ -1,6 +1,13 @@ package org.m1a2st.aop; import org.aopalliance.intercept.MethodInterceptor; +import org.m1a2st.aop.framework.AdvisorChainFactory; +import org.m1a2st.aop.framework.DefaultAdvisorChainFactory; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; /** * @Author m1a2st @@ -14,6 +21,9 @@ public class AdvisedSupport { private TargetSource targetSource; private MethodInterceptor methodInterceptor; private MethodMatcher methodMatcher; + AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory(); + private transient Map> methodCache; + private List advisors = new ArrayList<>(); public TargetSource getTargetSource() { return targetSource; @@ -31,6 +41,10 @@ public void setMethodInterceptor(MethodInterceptor methodInterceptor) { this.methodInterceptor = methodInterceptor; } + public void addAdvisor(Advisor advisor) { + advisors.add(advisor); + } + public MethodMatcher getMethodMatcher() { return methodMatcher; } @@ -46,4 +60,42 @@ public boolean isProxyTargetClass() { public void setProxyTargetClass(boolean proxyTargetClass) { this.proxyTargetClass = proxyTargetClass; } + + public Map> getMethodCache() { + return methodCache; + } + + public void setMethodCache(Map> methodCache) { + this.methodCache = methodCache; + } + + public AdvisorChainFactory getAdvisorChainFactory() { + return advisorChainFactory; + } + + public void setAdvisorChainFactory(AdvisorChainFactory advisorChainFactory) { + this.advisorChainFactory = advisorChainFactory; + } + + public List getAdvisors() { + return advisors; + } + + public void setAdvisors(List advisors) { + this.advisors = advisors; + } + + /** + * 用来返回方法的攔截器鏈 + */ + public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) { + Integer cacheKey = method.hashCode(); + List cached = this.methodCache.get(cacheKey); + if (cached == null) { + cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( + this, method, targetClass); + this.methodCache.put(cacheKey, cached); + } + return cached; + } } diff --git a/src/main/java/org/m1a2st/aop/AfterAdvice.java b/src/main/java/org/m1a2st/aop/AfterAdvice.java new file mode 100644 index 0000000..c18b10c --- /dev/null +++ b/src/main/java/org/m1a2st/aop/AfterAdvice.java @@ -0,0 +1,11 @@ +package org.m1a2st.aop; + +import org.aopalliance.aop.Advice; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public interface AfterAdvice extends Advice { +} diff --git a/src/main/java/org/m1a2st/aop/AfterReturningAdvice.java b/src/main/java/org/m1a2st/aop/AfterReturningAdvice.java new file mode 100644 index 0000000..7204dd8 --- /dev/null +++ b/src/main/java/org/m1a2st/aop/AfterReturningAdvice.java @@ -0,0 +1,13 @@ +package org.m1a2st.aop; + +import java.lang.reflect.Method; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public interface AfterReturningAdvice extends AfterAdvice { + + void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable; +} diff --git a/src/main/java/org/m1a2st/aop/autoproxy/DefaultAdvisorAutoProxyCreator.java b/src/main/java/org/m1a2st/aop/autoproxy/DefaultAdvisorAutoProxyCreator.java index 1508916..02156b3 100644 --- a/src/main/java/org/m1a2st/aop/autoproxy/DefaultAdvisorAutoProxyCreator.java +++ b/src/main/java/org/m1a2st/aop/autoproxy/DefaultAdvisorAutoProxyCreator.java @@ -1,7 +1,6 @@ package org.m1a2st.aop.autoproxy; import org.aopalliance.aop.Advice; -import org.aopalliance.intercept.MethodInterceptor; import org.m1a2st.aop.*; import org.m1a2st.aop.aspectj.AspectJExpressionPointcutAdvisor; import org.m1a2st.aop.framework.ProxyFactory; @@ -63,6 +62,7 @@ protected Object wrapIfNecessary(Object bean, String beanName) { } Collection advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values(); try { + ProxyFactory proxyFactory = new ProxyFactory(); for (AspectJExpressionPointcutAdvisor advisor : advisors) { ClassFilter classFilter = advisor.getPointcut().getClassFilter(); if (classFilter.matches(bean.getClass())) { @@ -71,11 +71,12 @@ protected Object wrapIfNecessary(Object bean, String beanName) { // set target source advisedSupport.setTargetSource(new TargetSource(bean)); - advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice()); + advisedSupport.addAdvisor(advisor); advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher()); return new ProxyFactory(advisedSupport).getProxy(); } } + if (!proxyFactory.getAdvisors().isEmpty()) return proxyFactory.getProxy(); } catch (Exception ex) { throw new BeansException("Error create proxy bean for: " + beanName, ex); } diff --git a/src/main/java/org/m1a2st/aop/framework/AdvisorChainFactory.java b/src/main/java/org/m1a2st/aop/framework/AdvisorChainFactory.java new file mode 100644 index 0000000..d251d89 --- /dev/null +++ b/src/main/java/org/m1a2st/aop/framework/AdvisorChainFactory.java @@ -0,0 +1,16 @@ +package org.m1a2st.aop.framework; + +import org.m1a2st.aop.AdvisedSupport; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public interface AdvisorChainFactory { + + List getInterceptorsAndDynamicInterceptionAdvice(AdvisedSupport config, Method method, Class targetClass); +} diff --git a/src/main/java/org/m1a2st/aop/framework/DefaultAdvisorChainFactory.java b/src/main/java/org/m1a2st/aop/framework/DefaultAdvisorChainFactory.java new file mode 100644 index 0000000..71b38d2 --- /dev/null +++ b/src/main/java/org/m1a2st/aop/framework/DefaultAdvisorChainFactory.java @@ -0,0 +1,44 @@ +package org.m1a2st.aop.framework; + +import org.aopalliance.intercept.MethodInterceptor; +import org.m1a2st.aop.AdvisedSupport; +import org.m1a2st.aop.Advisor; +import org.m1a2st.aop.MethodMatcher; +import org.m1a2st.aop.PointcutAdvisor; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public class DefaultAdvisorChainFactory implements AdvisorChainFactory { + + @Override + public List getInterceptorsAndDynamicInterceptionAdvice(AdvisedSupport config, Method method, Class targetClass) { + Advisor[] advisors = config.getAdvisors().toArray(new Advisor[0]); + List interceptorList = new ArrayList<>(advisors.length); + Class actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); + for (Advisor advisor : advisors) { + if (advisor instanceof PointcutAdvisor) { + // Add it conditionally. + PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; + // 校驗Advisor是否應用到當前類上 + if (pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { + MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); + boolean match; + // 校驗Advisor是否應用到當前方法上 + match = mm.matches(method, actualClass); + if (match) { + MethodInterceptor interceptor = (MethodInterceptor) advisor.getAdvice(); + interceptorList.add(interceptor); + } + } + } + } + return interceptorList; + } +} diff --git a/src/main/java/org/m1a2st/aop/framework/JdkDynamicAopProxy.java b/src/main/java/org/m1a2st/aop/framework/JdkDynamicAopProxy.java index 004688f..a123021 100644 --- a/src/main/java/org/m1a2st/aop/framework/JdkDynamicAopProxy.java +++ b/src/main/java/org/m1a2st/aop/framework/JdkDynamicAopProxy.java @@ -1,11 +1,11 @@ package org.m1a2st.aop.framework; -import org.aopalliance.intercept.MethodInterceptor; import org.m1a2st.aop.AdvisedSupport; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.util.List; /** * @Author m1a2st @@ -22,12 +22,21 @@ public JdkDynamicAopProxy(AdvisedSupport advised) { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) { - //代理方法 - MethodInterceptor methodInterceptor = advised.getMethodInterceptor(); - return methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method, args)); + // 獲取目標對象 + Object target = advised.getTargetSource().getTarget(); + Class targetClazz = target.getClass(); + Object retVal; + // 獲取攔截器鏈 + List chain = advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClazz); + if (chain == null || chain.isEmpty()) { + return method.invoke(target, args); + } else { + // 將攔截器統一封裝成ReflectiveMethodInvocation + ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClazz, chain); + // 依次執行每個攔截器的invoke方法 + retVal = invocation.proceed(); } - return method.invoke(advised.getTargetSource().getTarget(), args); + return retVal; } /** diff --git a/src/main/java/org/m1a2st/aop/framework/ProxyFactory.java b/src/main/java/org/m1a2st/aop/framework/ProxyFactory.java index 54fe882..b48a712 100644 --- a/src/main/java/org/m1a2st/aop/framework/ProxyFactory.java +++ b/src/main/java/org/m1a2st/aop/framework/ProxyFactory.java @@ -7,9 +7,12 @@ * @Date 2023/7/16 * @Version v1.0 */ -public class ProxyFactory { +public class ProxyFactory extends AdvisedSupport { - private final AdvisedSupport advisedSupport; + private AdvisedSupport advisedSupport; + + public ProxyFactory() { + } public ProxyFactory(AdvisedSupport advisedSupport) { this.advisedSupport = advisedSupport; @@ -20,7 +23,7 @@ public Object getProxy() { } private AopProxy createAopProxy() { - if (advisedSupport.isProxyTargetClass()) { + if (advisedSupport.isProxyTargetClass() || getTargetSource().getTargetClass().length == 0) { return new AnotherAopProxy(advisedSupport); } return new JdkDynamicAopProxy(advisedSupport); diff --git a/src/main/java/org/m1a2st/aop/framework/ReflectiveMethodInvocation.java b/src/main/java/org/m1a2st/aop/framework/ReflectiveMethodInvocation.java index 13f3ce1..cfce59f 100644 --- a/src/main/java/org/m1a2st/aop/framework/ReflectiveMethodInvocation.java +++ b/src/main/java/org/m1a2st/aop/framework/ReflectiveMethodInvocation.java @@ -1,9 +1,11 @@ package org.m1a2st.aop.framework; +import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; +import java.util.List; /** * @Author m1a2st @@ -12,14 +14,36 @@ */ public class ReflectiveMethodInvocation implements MethodInvocation { - private final Object target; - private final Method method; - private final Object[] arguments; + protected final Object proxy; + protected final Object target; + protected final Method method; + protected final Object[] arguments; + protected final Class targetClass; + protected final List interceptorsAndDynamicMethodMatchers; + private int currentInterceptorIndex = -1; - public ReflectiveMethodInvocation(Object target, Method method, Object[] arguments) { + public ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] arguments, Class targetClass, List chain) { + this.proxy = proxy; this.target = target; this.method = method; this.arguments = arguments; + this.targetClass = targetClass; + this.interceptorsAndDynamicMethodMatchers = chain; + } + + @Override + public Object proceed() throws Throwable { + // 初始currentInterceptorIndex為-1,每調用一次proceed就把currentInterceptorIndex+1 + if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { + // 當調用次數 = 攔截器個數時 + // 觸發當前method方法 + return method.invoke(this.target, this.arguments); + } + + Object interceptorOrInterceptionAdvice = + this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); + // 普通攔截器,直接觸發攔截器invoke方法 + return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } @Override @@ -32,10 +56,6 @@ public Object[] getArguments() { return arguments; } - @Override - public Object proceed() throws Throwable { - return method.invoke(target, arguments); - } @Override public Object getThis() { diff --git a/src/main/java/org/m1a2st/aop/framework/adapter/AfterReturningAdviceInterceptor.java b/src/main/java/org/m1a2st/aop/framework/adapter/AfterReturningAdviceInterceptor.java new file mode 100644 index 0000000..d496a50 --- /dev/null +++ b/src/main/java/org/m1a2st/aop/framework/adapter/AfterReturningAdviceInterceptor.java @@ -0,0 +1,30 @@ +package org.m1a2st.aop.framework.adapter; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.m1a2st.aop.AfterAdvice; +import org.m1a2st.aop.AfterReturningAdvice; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice { + + private AfterReturningAdvice advice; + + public AfterReturningAdviceInterceptor() { + } + + public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) { + this.advice = advice; + } + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + Object retVal = invocation.proceed(); + advice.afterReturning(retVal, invocation.getMethod(), invocation.getArguments(), invocation.getThis()); + return retVal; + } +} diff --git a/src/main/java/org/m1a2st/aop/framework/adapter/MethodBeforeAdviceInterceptor.java b/src/main/java/org/m1a2st/aop/framework/adapter/MethodBeforeAdviceInterceptor.java index 9cb2d5a..ba51062 100644 --- a/src/main/java/org/m1a2st/aop/framework/adapter/MethodBeforeAdviceInterceptor.java +++ b/src/main/java/org/m1a2st/aop/framework/adapter/MethodBeforeAdviceInterceptor.java @@ -3,6 +3,7 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.m1a2st.aop.BeforeAdvice; import org.m1a2st.aop.MethodBeforeAdvice; /** @@ -10,7 +11,7 @@ * @Date 2023/7/16 * @Version v1.0 */ -public class MethodBeforeAdviceInterceptor implements MethodInterceptor { +public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice { private MethodBeforeAdvice advice; diff --git a/src/main/java/org/m1a2st/beans/factory/config/BeanDefinition.java b/src/main/java/org/m1a2st/beans/factory/config/BeanDefinition.java index a7e8dfc..2981a78 100644 --- a/src/main/java/org/m1a2st/beans/factory/config/BeanDefinition.java +++ b/src/main/java/org/m1a2st/beans/factory/config/BeanDefinition.java @@ -27,6 +27,7 @@ public class BeanDefinition { private String scope = SCOPE_SINGLETON; private boolean singleton = true; private boolean prototype = false; + private boolean lazyInit = false; public BeanDefinition(Class beanClass, PropertyValues propertyValues) { this.beanClass = beanClass; @@ -83,6 +84,14 @@ public boolean isPrototype() { return prototype; } + public boolean isLazyInit() { + return lazyInit; + } + + public void setLazyInit(boolean lazyInit) { + this.lazyInit = lazyInit; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/org/m1a2st/beans/factory/support/DefaultListableBeanFactory.java b/src/main/java/org/m1a2st/beans/factory/support/DefaultListableBeanFactory.java index ff8aeb4..d139f83 100644 --- a/src/main/java/org/m1a2st/beans/factory/support/DefaultListableBeanFactory.java +++ b/src/main/java/org/m1a2st/beans/factory/support/DefaultListableBeanFactory.java @@ -72,9 +72,12 @@ public BeanDefinition getBeanDefinition(String beanName) throws BeansException { @Override public void preInstantiateSingletons() throws BeansException { - for (String beanName : beanDefinitionMap.keySet()) { - getBean(beanName); - } + beanDefinitionMap.forEach((beanName, beanDefinition) -> { + // 只有當bean是單例且不為延遲初始化時,才進行bean的初始化動作 + if (beanDefinition.isSingleton() && !beanDefinition.isLazyInit()) { + getBean(beanName); + } + }); } @Override diff --git a/src/main/java/org/m1a2st/beans/factory/xml/XmlBeanDefinitionReader.java b/src/main/java/org/m1a2st/beans/factory/xml/XmlBeanDefinitionReader.java index 79b85e8..73fdda2 100644 --- a/src/main/java/org/m1a2st/beans/factory/xml/XmlBeanDefinitionReader.java +++ b/src/main/java/org/m1a2st/beans/factory/xml/XmlBeanDefinitionReader.java @@ -38,6 +38,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { public static final String SCOPE_ATTRIBUTE = "scope"; public static final String BASE_PACKAGE_ATTRIBUTE = "base-package"; public static final String COMPONENT_SCAN_ELEMENT = "component-scan"; + public static final String LAZY_INIT_ATTRIBUTE = "lazyInit"; public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) { super(registry); @@ -94,6 +95,7 @@ protected void doLoadBeanDefinitions(InputStream inputStream) throws DocumentExc String initMethodName = bean.attributeValue(INIT_METHOD_ATTRIBUTE); String destroyMethodName = bean.attributeValue(DESTROY_METHOD_ATTRIBUTE); String beanScope = bean.attributeValue(SCOPE_ATTRIBUTE); + String lazyInit = bean.attributeValue(LAZY_INIT_ATTRIBUTE); Class clazz; try { @@ -111,6 +113,7 @@ protected void doLoadBeanDefinitions(InputStream inputStream) throws DocumentExc BeanDefinition beanDefinition = new BeanDefinition(clazz); beanDefinition.setInitMethodName(initMethodName); beanDefinition.setDestroyMethodName(destroyMethodName); + beanDefinition.setLazyInit(Boolean.parseBoolean(lazyInit)); if (StrUtil.isNotEmpty(beanScope)) { beanDefinition.setScope(beanScope); } diff --git a/src/main/test/java/org/m1a2st/beans/aop/DynamicProxyTest.java b/src/main/test/java/org/m1a2st/beans/aop/DynamicProxyTest.java index c3c60ea..9e55143 100644 --- a/src/main/test/java/org/m1a2st/beans/aop/DynamicProxyTest.java +++ b/src/main/test/java/org/m1a2st/beans/aop/DynamicProxyTest.java @@ -5,13 +5,13 @@ import org.junit.jupiter.api.Test; import org.m1a2st.aop.AdvisedSupport; import org.m1a2st.aop.ClassFilter; -import org.m1a2st.aop.MethodMatcher; import org.m1a2st.aop.TargetSource; -import org.m1a2st.aop.aspectj.AspectJExpressionPointcut; import org.m1a2st.aop.aspectj.AspectJExpressionPointcutAdvisor; import org.m1a2st.aop.framework.JdkDynamicAopProxy; import org.m1a2st.aop.framework.ProxyFactory; +import org.m1a2st.aop.framework.adapter.AfterReturningAdviceInterceptor; import org.m1a2st.aop.framework.adapter.MethodBeforeAdviceInterceptor; +import org.m1a2st.beans.common.WorldServiceAfterReturnAdvice; import org.m1a2st.beans.common.WorldServiceBeforeAdvice; import org.m1a2st.beans.common.WorldServiceInterceptor; import org.m1a2st.beans.service.WorldService; @@ -33,12 +33,16 @@ public void setup() { advisedSupport = new AdvisedSupport(); TargetSource targetSource = new TargetSource(worldService); WorldServiceInterceptor interceptor = new WorldServiceInterceptor(); - MethodMatcher methodMatcher = - new AspectJExpressionPointcut("execution(* org.m1a2st.beans.service.WorldService.*(..))") - .getMethodMatcher(); + String expression = "execution(* org.m1a2st.beans.service.WorldService.*(..))"; + AspectJExpressionPointcutAdvisor advisor = + new AspectJExpressionPointcutAdvisor(); + advisor.setExpression(expression); + AfterReturningAdviceInterceptor methodInterceptor = + new AfterReturningAdviceInterceptor(new WorldServiceAfterReturnAdvice()); + advisor.setAdvice(methodInterceptor); advisedSupport.setTargetSource(targetSource); advisedSupport.setMethodInterceptor(interceptor); - advisedSupport.setMethodMatcher(methodMatcher); + advisedSupport.addAdvisor(advisor); } @Test @@ -51,7 +55,7 @@ public void testJdkDynamicProxy() { public void testProxyFactory() { // 使用JDK動態代理 advisedSupport.setProxyTargetClass(false); - WorldService proxy = (WorldService) new ProxyFactory(advisedSupport).getProxy(); + WorldService proxy = (WorldService) new ProxyFactory().getProxy(); proxy.explode(); // 使用不同的代理 // advisedSupport.setProxyTargetClass(true); diff --git a/src/main/test/java/org/m1a2st/beans/aop/ProxyFactoryTest.java b/src/main/test/java/org/m1a2st/beans/aop/ProxyFactoryTest.java new file mode 100644 index 0000000..fd73ef6 --- /dev/null +++ b/src/main/test/java/org/m1a2st/beans/aop/ProxyFactoryTest.java @@ -0,0 +1,49 @@ +package org.m1a2st.beans.aop; + +import org.junit.jupiter.api.Test; +import org.m1a2st.aop.TargetSource; +import org.m1a2st.aop.aspectj.AspectJExpressionPointcutAdvisor; +import org.m1a2st.aop.framework.ProxyFactory; +import org.m1a2st.aop.framework.adapter.AfterReturningAdviceInterceptor; +import org.m1a2st.aop.framework.adapter.MethodBeforeAdviceInterceptor; +import org.m1a2st.beans.common.WorldServiceAfterReturnAdvice; +import org.m1a2st.beans.common.WorldServiceBeforeAdvice; +import org.m1a2st.beans.service.WorldService; +import org.m1a2st.beans.service.WorldServiceImpl; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public class ProxyFactoryTest { + + @Test + public void testAdvisor() throws Exception{ + WorldService worldService = new WorldServiceImpl(); + + // Advisor 是 Advice的子介面,用於封裝 Pointcut 和 Advice 的關係 + String expression = "execution(* org.m1a2st.beans.service.WorldService.explode(..))"; + // 設定切點和通知 + AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor(); + advisor.setExpression(expression); + + MethodBeforeAdviceInterceptor methodInterceptor = + new MethodBeforeAdviceInterceptor(new WorldServiceBeforeAdvice()); + advisor.setAdvice(methodInterceptor); + + AspectJExpressionPointcutAdvisor advisor1 = new AspectJExpressionPointcutAdvisor(); + advisor1.setExpression(expression); + AfterReturningAdviceInterceptor afterReturningAdviceInterceptor=new AfterReturningAdviceInterceptor(new WorldServiceAfterReturnAdvice()); + advisor1.setAdvice(afterReturningAdviceInterceptor); + + ProxyFactory factory = new ProxyFactory(); + TargetSource targetSource = new TargetSource(worldService); + factory.setTargetSource(targetSource); + factory.setProxyTargetClass(true); + factory.addAdvisor(advisor); + factory.addAdvisor(advisor1); + WorldService proxy = (WorldService) factory.getProxy(); + proxy.explode(); + } +} diff --git a/src/main/test/java/org/m1a2st/beans/common/WorldServiceAfterReturnAdvice.java b/src/main/test/java/org/m1a2st/beans/common/WorldServiceAfterReturnAdvice.java new file mode 100644 index 0000000..137851f --- /dev/null +++ b/src/main/test/java/org/m1a2st/beans/common/WorldServiceAfterReturnAdvice.java @@ -0,0 +1,18 @@ +package org.m1a2st.beans.common; + +import org.m1a2st.aop.AfterReturningAdvice; + +import java.lang.reflect.Method; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public class WorldServiceAfterReturnAdvice implements AfterReturningAdvice { + + @Override + public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { + System.out.println("WorldServiceAfterReturnAdvice afterReturning"); + } +} diff --git a/src/main/test/java/org/m1a2st/beans/ioc/LazyInitTest.java b/src/main/test/java/org/m1a2st/beans/ioc/LazyInitTest.java new file mode 100644 index 0000000..4fbb9cb --- /dev/null +++ b/src/main/test/java/org/m1a2st/beans/ioc/LazyInitTest.java @@ -0,0 +1,22 @@ +package org.m1a2st.beans.ioc; + +import org.junit.jupiter.api.Test; +import org.m1a2st.beans.bean.Car; +import org.m1a2st.context.support.ClassPathXmlApplicationContext; + +import java.util.concurrent.TimeUnit; + +/** + * @Author m1a2st + * @Date 2023/7/26 + * @Version v1.0 + */ +public class LazyInitTest { + @Test + public void testLazyInit() throws InterruptedException { + ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:lazy-test.xml"); + System.out.println(System.currentTimeMillis()+":applicationContext-over"); + TimeUnit.SECONDS.sleep(1); + Car c= (Car) applicationContext.getBean("car"); + } +}