From 43928fa737587aac66747d788e2328179ff0bf2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=93=E5=87=A4=E9=BA=92?= Date: Mon, 12 Mar 2018 21:05:50 +0800 Subject: [PATCH 1/6] add ignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea From a1dcb8ce3bbbbb91393b0724f7a8604780b91c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=93=E5=87=A4=E9=BA=92?= Date: Tue, 13 Mar 2018 22:05:32 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0eventPublisher=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0@AutoWired=E6=B3=A8=E8=A7=A3=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=83=A8=E5=88=86=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + pom.xml | 11 +++- .../AspectJAwareAdvisorAutoProxyCreator.java | 5 ++ .../aop/AspectJExpressionPointcut.java | 1 + .../codecraft/tinyioc/aop/Cglib2AopProxy.java | 3 + .../tinyioc/aop/JdkDynamicAopProxy.java | 1 + .../aop/ReflectiveMethodInvocation.java | 1 + .../us/codecraft/tinyioc/beans/AutoWired.java | 24 +++++++ .../beans/factory/AbstractBeanFactory.java | 6 ++ .../factory/AutowireCapableBeanFactory.java | 59 +++++++++++------- .../context/AbstractApplicationContext.java | 42 ++++++------- .../tinyioc/context/ApplicationContext.java | 3 +- .../ClassPathXmlApplicationContext.java | 62 ++++++++++++++----- .../message/ApplicationEventPublisher.java | 14 +++++ .../tinyioc/message/EventListener.java | 20 ++++++ .../us/codecraft/tinyioc/message/Message.java | 16 +++++ .../tinyioc/message/MessageHandlerHolder.java | 42 +++++++++++++ .../message/MessageHandlerInvocation.java | 33 ++++++++++ .../tinyioc/HelloWorldServiceImpl.java | 23 ++++--- .../codecraft/tinyioc/OutputServiceImpl.java | 12 ++++ .../tinyioc/aop/TimerInterceptor.java | 6 ++ .../context/ApplicationContextTest.java | 3 + 22 files changed, 314 insertions(+), 74 deletions(-) create mode 100644 src/main/java/us/codecraft/tinyioc/beans/AutoWired.java create mode 100644 src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java create mode 100644 src/main/java/us/codecraft/tinyioc/message/EventListener.java create mode 100644 src/main/java/us/codecraft/tinyioc/message/Message.java create mode 100644 src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java create mode 100644 src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java diff --git a/.gitignore b/.gitignore index 485dee6..af515ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .idea +target/ diff --git a/pom.xml b/pom.xml index 00fe1de..ae95495 100644 --- a/pom.xml +++ b/pom.xml @@ -29,10 +29,15 @@ + + org.projectlombok + lombok + 1.16.18 + junit junit - 4.7 + 4.12 test @@ -59,8 +64,8 @@ maven-compiler-plugin 3.1 - 1.6 - 1.6 + 1.8 + 1.8 UTF-8 diff --git a/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java b/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java index e1ce4d9..c24695c 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java +++ b/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java @@ -10,15 +10,18 @@ /** * @author yihua.huang@dianping.com */ +// 本身就是一个Bean public class AspectJAwareAdvisorAutoProxyCreator implements BeanPostProcessor, BeanFactoryAware { private AbstractBeanFactory beanFactory; + //初始化之前的一次回调 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception { return bean; } + //初始化后的一次回调 对所有的bean做一次增强 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception { if (bean instanceof AspectJExpressionPointcutAdvisor) { @@ -38,12 +41,14 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw TargetSource targetSource = new TargetSource(bean, bean.getClass(), bean.getClass().getInterfaces()); advisedSupport.setTargetSource(targetSource); + //此时返回的是CGLib代理的对象 并非原始的对象 return advisedSupport.getProxy(); } } return bean; } + //初始化的时候 注入beanFactory @Override public void setBeanFactory(BeanFactory beanFactory) throws Exception { this.beanFactory = (AbstractBeanFactory) beanFactory; diff --git a/src/main/java/us/codecraft/tinyioc/aop/AspectJExpressionPointcut.java b/src/main/java/us/codecraft/tinyioc/aop/AspectJExpressionPointcut.java index 8e69d69..1174378 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/AspectJExpressionPointcut.java +++ b/src/main/java/us/codecraft/tinyioc/aop/AspectJExpressionPointcut.java @@ -18,6 +18,7 @@ public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodM private String expression; + //切点表达式 private PointcutExpression pointcutExpression; private static final Set DEFAULT_SUPPORTED_PRIMITIVES = new HashSet(); diff --git a/src/main/java/us/codecraft/tinyioc/aop/Cglib2AopProxy.java b/src/main/java/us/codecraft/tinyioc/aop/Cglib2AopProxy.java index 4831097..d3c121b 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/Cglib2AopProxy.java +++ b/src/main/java/us/codecraft/tinyioc/aop/Cglib2AopProxy.java @@ -36,8 +36,10 @@ private DynamicAdvisedInterceptor(AdvisedSupport advised) { this.delegateMethodInterceptor = advised.getMethodInterceptor(); } + // 代理对象 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + // 如果match匹配到 那么代理 if (advised.getMethodMatcher() == null || advised.getMethodMatcher().matches(method, advised.getTargetSource().getTargetClass())) { return delegateMethodInterceptor.invoke(new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy)); @@ -46,6 +48,7 @@ public Object intercept(Object obj, Method method, Object[] args, MethodProxy pr } } + // 创建一个原始的方法调用 private static class CglibMethodInvocation extends ReflectiveMethodInvocation { private final MethodProxy methodProxy; diff --git a/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java b/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java index 4667cd2..01738c5 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java +++ b/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java @@ -27,6 +27,7 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg MethodInterceptor methodInterceptor = advised.getMethodInterceptor(); if (advised.getMethodMatcher() != null && advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) { + // 执行拦截的方法 , 由拦截的方法负责调用 真实的bean方法 return methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method, args)); } else { diff --git a/src/main/java/us/codecraft/tinyioc/aop/ReflectiveMethodInvocation.java b/src/main/java/us/codecraft/tinyioc/aop/ReflectiveMethodInvocation.java index 78d3582..2d9281c 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/ReflectiveMethodInvocation.java +++ b/src/main/java/us/codecraft/tinyioc/aop/ReflectiveMethodInvocation.java @@ -16,6 +16,7 @@ public class ReflectiveMethodInvocation implements MethodInvocation { protected Object[] arguments; + //反射方法代理类 持有对象 方法本身 方法调用的参数 public ReflectiveMethodInvocation(Object target, Method method, Object[] arguments) { this.target = target; this.method = method; diff --git a/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java b/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java new file mode 100644 index 0000000..3dc0793 --- /dev/null +++ b/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java @@ -0,0 +1,24 @@ +package us.codecraft.tinyioc.beans; + +/** + * @author 邓凤麒 + * 创建时间:13/03/2018 16:42 + * 创建原因: + **/ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +//此处Autowired 只适用在字段上 + +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface AutoWired { + +} diff --git a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java index 1695f87..7947d04 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java +++ b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java @@ -37,12 +37,17 @@ public Object getBean(String name) throws Exception { protected Object initializeBean(Object bean, String name) throws Exception { for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { + //初始化之前 bean = beanPostProcessor.postProcessBeforeInitialization(bean, name); } // TODO:call initialize method for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { + //初始化之后 对bean进行增强 原始的bean 被代理bean 的引用持有 + Object preBean = bean; bean = beanPostProcessor.postProcessAfterInitialization(bean, name); + //断言 增强后的 bean 是原始bean的父类 + assert preBean.getClass().isAssignableFrom(bean.getClass()); } return bean; } @@ -78,6 +83,7 @@ public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) throws Exc this.beanPostProcessors.add(beanPostProcessor); } + // 所有的bean都是从beanDefinition中取出来的, public List getBeansForType(Class type) throws Exception { List beans = new ArrayList(); for (String beanDefinitionName : beanDefinitionNames) { diff --git a/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java b/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java index 740bcfb..294a22e 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java +++ b/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java @@ -2,42 +2,53 @@ import us.codecraft.tinyioc.BeanReference; import us.codecraft.tinyioc.aop.BeanFactoryAware; +import us.codecraft.tinyioc.beans.AutoWired; import us.codecraft.tinyioc.beans.BeanDefinition; import us.codecraft.tinyioc.beans.PropertyValue; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.List; /** * 可自动装配内容的BeanFactory - * * @author yihua.huang@dianping.com */ public class AutowireCapableBeanFactory extends AbstractBeanFactory { - protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception { - if (bean instanceof BeanFactoryAware) { - ((BeanFactoryAware) bean).setBeanFactory(this); - } - for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) { - Object value = propertyValue.getValue(); - if (value instanceof BeanReference) { - BeanReference beanReference = (BeanReference) value; - value = getBean(beanReference.getName()); - } + protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception { + if (bean instanceof BeanFactoryAware) { + ((BeanFactoryAware) bean).setBeanFactory(this); + } + for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) { + Object value = propertyValue.getValue(); + if (value instanceof BeanReference) { + BeanReference beanReference = (BeanReference) value; + value = getBean(beanReference.getName()); + } - try { - Method declaredMethod = bean.getClass().getDeclaredMethod( - "set" + propertyValue.getName().substring(0, 1).toUpperCase() - + propertyValue.getName().substring(1), value.getClass()); - declaredMethod.setAccessible(true); + try { + Method declaredMethod = bean.getClass().getDeclaredMethod( + "set" + propertyValue.getName().substring(0, 1).toUpperCase() + + propertyValue.getName().substring(1), value.getClass()); + declaredMethod.setAccessible(true); - declaredMethod.invoke(bean, value); - } catch (NoSuchMethodException e) { - Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName()); - declaredField.setAccessible(true); - declaredField.set(bean, value); - } - } - } + declaredMethod.invoke(bean, value); + } catch (NoSuchMethodException e) { + Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName()); + declaredField.setAccessible(true); + declaredField.set(bean, value); + } + } + for (Field field : bean.getClass().getDeclaredFields()) { + if (field.isAnnotationPresent(AutoWired.class)) { + field.setAccessible(true); + List beansForType = getBeansForType(field.getType()); + if (beansForType.size() != 1) { + throw new RuntimeException("可选注入类型 超过1个, 或者没有可选注入类型"); + } + field.set(bean, beansForType.get(0)); + } + } + } } diff --git a/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java b/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java index 0e78e7a..961de9b 100644 --- a/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java +++ b/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java @@ -9,33 +9,33 @@ * @author yihua.huang@dianping.com */ public abstract class AbstractApplicationContext implements ApplicationContext { - protected AbstractBeanFactory beanFactory; + protected AbstractBeanFactory beanFactory; - public AbstractApplicationContext(AbstractBeanFactory beanFactory) { - this.beanFactory = beanFactory; - } + public AbstractApplicationContext(AbstractBeanFactory beanFactory) { + this.beanFactory = beanFactory; + } - public void refresh() throws Exception { - loadBeanDefinitions(beanFactory); - registerBeanPostProcessors(beanFactory); - onRefresh(); - } + public void refresh() throws Exception { + loadBeanDefinitions(beanFactory); + registerBeanPostProcessors(beanFactory); + onRefresh(); + } - protected abstract void loadBeanDefinitions(AbstractBeanFactory beanFactory) throws Exception; + protected abstract void loadBeanDefinitions(AbstractBeanFactory beanFactory) throws Exception; - protected void registerBeanPostProcessors(AbstractBeanFactory beanFactory) throws Exception { - List beanPostProcessors = beanFactory.getBeansForType(BeanPostProcessor.class); - for (Object beanPostProcessor : beanPostProcessors) { - beanFactory.addBeanPostProcessor((BeanPostProcessor) beanPostProcessor); - } - } + protected void registerBeanPostProcessors(AbstractBeanFactory beanFactory) throws Exception { + List beanPostProcessors = beanFactory.getBeansForType(BeanPostProcessor.class); + for (Object beanPostProcessor : beanPostProcessors) { + beanFactory.addBeanPostProcessor((BeanPostProcessor) beanPostProcessor); + } + } - protected void onRefresh() throws Exception{ + protected void onRefresh() throws Exception { beanFactory.preInstantiateSingletons(); } - @Override - public Object getBean(String name) throws Exception { - return beanFactory.getBean(name); - } + @Override + public Object getBean(String name) throws Exception { + return beanFactory.getBean(name); + } } diff --git a/src/main/java/us/codecraft/tinyioc/context/ApplicationContext.java b/src/main/java/us/codecraft/tinyioc/context/ApplicationContext.java index 7cc1902..9887fff 100644 --- a/src/main/java/us/codecraft/tinyioc/context/ApplicationContext.java +++ b/src/main/java/us/codecraft/tinyioc/context/ApplicationContext.java @@ -1,9 +1,10 @@ package us.codecraft.tinyioc.context; import us.codecraft.tinyioc.beans.factory.BeanFactory; +import us.codecraft.tinyioc.message.ApplicationEventPublisher; /** * @author yihua.huang@dianping.com */ -public interface ApplicationContext extends BeanFactory { +public interface ApplicationContext extends BeanFactory, ApplicationEventPublisher{ } diff --git a/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java b/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java index c2ffd76..191fbf7 100644 --- a/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java +++ b/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java @@ -5,6 +5,8 @@ import us.codecraft.tinyioc.beans.factory.AutowireCapableBeanFactory; import us.codecraft.tinyioc.beans.io.ResourceLoader; import us.codecraft.tinyioc.beans.xml.XmlBeanDefinitionReader; +import us.codecraft.tinyioc.message.MessageHandlerHolder; +import us.codecraft.tinyioc.message.MessageHandlerInvocation; import java.util.Map; @@ -13,25 +15,51 @@ */ public class ClassPathXmlApplicationContext extends AbstractApplicationContext { - private String configLocation; + private String configLocation; - public ClassPathXmlApplicationContext(String configLocation) throws Exception { - this(configLocation, new AutowireCapableBeanFactory()); - } + private MessageHandlerHolder messageHandlerHolder = new MessageHandlerHolder(); - public ClassPathXmlApplicationContext(String configLocation, AbstractBeanFactory beanFactory) throws Exception { - super(beanFactory); - this.configLocation = configLocation; - refresh(); - } + public ClassPathXmlApplicationContext(String configLocation) throws Exception { + this(configLocation, new AutowireCapableBeanFactory()); + } - @Override - protected void loadBeanDefinitions(AbstractBeanFactory beanFactory) throws Exception { - XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader()); - xmlBeanDefinitionReader.loadBeanDefinitions(configLocation); - for (Map.Entry beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) { - beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue()); - } - } + public ClassPathXmlApplicationContext(String configLocation, AbstractBeanFactory beanFactory) throws Exception { + super(beanFactory); + this.configLocation = configLocation; + refresh(); + } + @Override + protected void loadBeanDefinitions(AbstractBeanFactory beanFactory) throws Exception { + XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader()); + xmlBeanDefinitionReader.loadBeanDefinitions(configLocation); + for (Map.Entry beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) { + beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue()); + } + //将自身注入进bean容器 + registerSelf(); + //消息处理者handler 扫描所有的bean 对方法上有EventListener注解的 + beanFactory.addBeanPostProcessor(messageHandlerHolder); + } + + private void registerSelf() throws Exception { + BeanDefinition self = new BeanDefinition(); + self.setBeanClassName(this.getClass().getName()); + self.setBeanClass(this.getClass()); + self.setBean(this); + beanFactory.registerBeanDefinition("applicationContext", self); + } + + @Override + public void publishEvent(Object object) { + for (MessageHandlerInvocation messageHandlerInvocation : messageHandlerHolder.getMessageHandlers()) { + if (messageHandlerInvocation.getParameterType().getType().isInstance(object)) { + try { + messageHandlerInvocation.handleMessage(object); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + } } diff --git a/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java b/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java new file mode 100644 index 0000000..b59b228 --- /dev/null +++ b/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java @@ -0,0 +1,14 @@ +package us.codecraft.tinyioc.message; + +/** + * @author 邓凤麒 + * 创建时间:13/03/2018 15:47 + * 创建原因: + **/ +public interface ApplicationEventPublisher { + /** + * 发布消息 + * @param object + */ + void publishEvent(Object object); +} diff --git a/src/main/java/us/codecraft/tinyioc/message/EventListener.java b/src/main/java/us/codecraft/tinyioc/message/EventListener.java new file mode 100644 index 0000000..8464a99 --- /dev/null +++ b/src/main/java/us/codecraft/tinyioc/message/EventListener.java @@ -0,0 +1,20 @@ +package us.codecraft.tinyioc.message; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author 邓凤麒 + * 创建时间:13/03/2018 15:52 + * 创建原因: + **/ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface EventListener { +} diff --git a/src/main/java/us/codecraft/tinyioc/message/Message.java b/src/main/java/us/codecraft/tinyioc/message/Message.java new file mode 100644 index 0000000..24d493d --- /dev/null +++ b/src/main/java/us/codecraft/tinyioc/message/Message.java @@ -0,0 +1,16 @@ +package us.codecraft.tinyioc.message; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @author 邓凤麒 + * 创建时间:13/03/2018 16:22 + * 创建原因: + **/ +@Data +@AllArgsConstructor +public class Message { + + private String msg; +} diff --git a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java new file mode 100644 index 0000000..6f95219 --- /dev/null +++ b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java @@ -0,0 +1,42 @@ +package us.codecraft.tinyioc.message; + +import us.codecraft.tinyioc.beans.BeanPostProcessor; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +/** + * @author 邓凤麒 + * 创建时间:13/03/2018 15:51 + * 创建原因: + **/ +public class MessageHandlerHolder implements BeanPostProcessor { + + private List messageHandlers = new ArrayList<>(); + + public List getMessageHandlers() { + return messageHandlers; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception { + for (Method method : bean.getClass().getMethods()) { + if (method.isAnnotationPresent(EventListener.class)) { + if (method.getParameters().length == 1) { + MessageHandlerInvocation messageHandlerInvocation = new MessageHandlerInvocation( + method, + method.getParameters()[0], bean); + messageHandlers.add(messageHandlerInvocation); + } + } + } + return bean; + } + +} diff --git a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java new file mode 100644 index 0000000..f0f5d50 --- /dev/null +++ b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java @@ -0,0 +1,33 @@ +package us.codecraft.tinyioc.message; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; + +/** + * @author 邓凤麒 + * 创建时间:13/03/2018 15:57 + * 创建原因: + **/ +public class MessageHandlerInvocation { + + private Method method; + + public Parameter getParameterType() { + return parameterType; + } + + private Parameter parameterType; + + private Object target; + + public MessageHandlerInvocation(Method method, Parameter parameter, Object target) { + this.method = method; + this.parameterType = parameter; + this.target = target; + } + + public void handleMessage(Object object) throws InvocationTargetException, IllegalAccessException { + method.invoke(target, object); + } +} diff --git a/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java b/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java index 0958882..dff7a58 100644 --- a/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java +++ b/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java @@ -1,25 +1,32 @@ package us.codecraft.tinyioc; +import lombok.Data; +import us.codecraft.tinyioc.beans.AutoWired; +import us.codecraft.tinyioc.message.ApplicationEventPublisher; +import us.codecraft.tinyioc.message.EventListener; +import us.codecraft.tinyioc.message.Message; + /** * @author yihua.huang@dianping.com */ +@Data public class HelloWorldServiceImpl implements HelloWorldService { private String text; private OutputService outputService; + @AutoWired + private ApplicationEventPublisher applicationEventPublisher; + @Override - public void helloWorld(){ + public void helloWorld() { outputService.output(text); } - public void setText(String text) { - this.text = text; + @EventListener + public void handleMessage(String msg) { + System.out.println("Handle type String's message is:" + msg); + applicationEventPublisher.publishEvent(new Message("through autowired publisher publish this message")); } - - public void setOutputService(OutputService outputService) { - this.outputService = outputService; - } - } diff --git a/src/test/java/us/codecraft/tinyioc/OutputServiceImpl.java b/src/test/java/us/codecraft/tinyioc/OutputServiceImpl.java index a840fe8..eb1d718 100644 --- a/src/test/java/us/codecraft/tinyioc/OutputServiceImpl.java +++ b/src/test/java/us/codecraft/tinyioc/OutputServiceImpl.java @@ -1,13 +1,25 @@ package us.codecraft.tinyioc; +import lombok.Data; +import us.codecraft.tinyioc.message.EventListener; +import us.codecraft.tinyioc.message.Message; + /** * @author yihua.huang@dianping.com */ +@Data public class OutputServiceImpl implements OutputService { + HelloWorldService helloWorldService; + @Override public void output(String text){ System.out.println(text); } + @EventListener + public void handleMessage(Message message){ + System.out.println("Handle message'type is Message msg is: " + message.getMsg()); + } + } diff --git a/src/test/java/us/codecraft/tinyioc/aop/TimerInterceptor.java b/src/test/java/us/codecraft/tinyioc/aop/TimerInterceptor.java index 4547c51..eee92af 100644 --- a/src/test/java/us/codecraft/tinyioc/aop/TimerInterceptor.java +++ b/src/test/java/us/codecraft/tinyioc/aop/TimerInterceptor.java @@ -8,11 +8,17 @@ */ public class TimerInterceptor implements MethodInterceptor { + //代理回调 @Override public Object invoke(MethodInvocation invocation) throws Throwable { long time = System.nanoTime(); System.out.println("Invocation of Method " + invocation.getMethod().getName() + " start!"); + //执行真正的bean方法前 + + //执行bean原始方法 Object proceed = invocation.proceed(); + + //执行真正的bean方法后 System.out.println("Invocation of Method " + invocation.getMethod().getName() + " end! takes " + (System.nanoTime() - time) + " nanoseconds."); return proceed; diff --git a/src/test/java/us/codecraft/tinyioc/context/ApplicationContextTest.java b/src/test/java/us/codecraft/tinyioc/context/ApplicationContextTest.java index 5d57588..93afb68 100644 --- a/src/test/java/us/codecraft/tinyioc/context/ApplicationContextTest.java +++ b/src/test/java/us/codecraft/tinyioc/context/ApplicationContextTest.java @@ -2,6 +2,7 @@ import org.junit.Test; import us.codecraft.tinyioc.HelloWorldService; +import us.codecraft.tinyioc.message.Message; /** * @author yihua.huang@dianping.com @@ -19,6 +20,8 @@ public void test() throws Exception { public void testPostBeanProcessor() throws Exception { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("tinyioc-postbeanprocessor.xml"); HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService"); + applicationContext.publishEvent("test"); + applicationContext.publishEvent(new Message("test")); helloWorldService.helloWorld(); } } From fbd0213ec3aaa189e97ecf582176d1affe725392 Mon Sep 17 00:00:00 2001 From: winters Date: Fri, 23 Mar 2018 22:11:51 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E6=B3=A8=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../us/codecraft/tinyioc/beans/AutoWired.java | 4 +- .../beans/factory/AbstractBeanFactory.java | 159 ++++++++++-------- .../factory/AutowireCapableBeanFactory.java | 9 + .../context/AbstractApplicationContext.java | 31 ++++ .../ClassPathXmlApplicationContext.java | 27 --- .../message/ApplicationEventPublisher.java | 2 +- .../tinyioc/message/EventListener.java | 2 +- .../us/codecraft/tinyioc/message/Message.java | 2 +- .../tinyioc/message/MessageHandlerHolder.java | 2 +- .../message/MessageHandlerInvocation.java | 2 +- .../tinyioc/HelloWorldServiceImpl.java | 7 +- 11 files changed, 140 insertions(+), 107 deletions(-) diff --git a/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java b/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java index 3dc0793..83a3b85 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java +++ b/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java @@ -1,7 +1,7 @@ package us.codecraft.tinyioc.beans; /** - * @author 邓凤麒 + * @author winters * 创建时间:13/03/2018 16:42 * 创建原因: **/ @@ -15,7 +15,7 @@ //此处Autowired 只适用在字段上 -@Target({ElementType.FIELD}) +@Target({ElementType.FIELD,ElementType.CONSTRUCTOR}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented diff --git a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java index 7947d04..b1fc8ee 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java +++ b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java @@ -1,8 +1,10 @@ package us.codecraft.tinyioc.beans.factory; +import us.codecraft.tinyioc.beans.AutoWired; import us.codecraft.tinyioc.beans.BeanDefinition; import us.codecraft.tinyioc.beans.BeanPostProcessor; +import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -14,84 +16,97 @@ */ public abstract class AbstractBeanFactory implements BeanFactory { - private Map beanDefinitionMap = new ConcurrentHashMap(); - - private final List beanDefinitionNames = new ArrayList(); - - private List beanPostProcessors = new ArrayList(); - - @Override - public Object getBean(String name) throws Exception { - BeanDefinition beanDefinition = beanDefinitionMap.get(name); - if (beanDefinition == null) { - throw new IllegalArgumentException("No bean named " + name + " is defined"); - } - Object bean = beanDefinition.getBean(); - if (bean == null) { - bean = doCreateBean(beanDefinition); + private final List beanDefinitionNames = new ArrayList(); + private Map beanDefinitionMap = new ConcurrentHashMap(); + private List beanPostProcessors = new ArrayList(); + + @Override + public Object getBean(String name) throws Exception { + BeanDefinition beanDefinition = beanDefinitionMap.get(name); + if (beanDefinition == null) { + throw new IllegalArgumentException("No bean named " + name + " is defined"); + } + Object bean = beanDefinition.getBean(); + if (bean == null) { + bean = doCreateBean(beanDefinition); bean = initializeBean(bean, name); beanDefinition.setBean(bean); - } - return bean; - } - - protected Object initializeBean(Object bean, String name) throws Exception { - for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { - //初始化之前 - bean = beanPostProcessor.postProcessBeforeInitialization(bean, name); - } - - // TODO:call initialize method - for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { - //初始化之后 对bean进行增强 原始的bean 被代理bean 的引用持有 + } + return bean; + } + + protected Object initializeBean(Object bean, String name) throws Exception { + for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { + //初始化之前 + bean = beanPostProcessor.postProcessBeforeInitialization(bean, name); + } + + // TODO:call initialize method + for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { + //初始化之后 对bean进行增强 原始的bean 被代理bean 的引用持有 Object preBean = bean; bean = beanPostProcessor.postProcessAfterInitialization(bean, name); //断言 增强后的 bean 是原始bean的父类 assert preBean.getClass().isAssignableFrom(bean.getClass()); - } + } + return bean; + } + + protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception { + Constructor[] constructors = beanDefinition.getBeanClass().getConstructors(); + for (int i = 0; i < constructors.length; i++) { + if (constructors[i].isAnnotationPresent(AutoWired.class)) { + List objs = new ArrayList(); + for (Class clazz : constructors[i].getParameterTypes()) { + List beansForType = getBeansForType(clazz); + if (beansForType.size() == 1) { + objs.add(beansForType.get(0)); + } + } + if (objs.size() == constructors[i].getParameterCount()) { + return constructors[i].newInstance(objs.toArray()); + } + } + } + return beanDefinition.getBeanClass().newInstance(); + } + + public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception { + beanDefinitionMap.put(name, beanDefinition); + beanDefinitionNames.add(name); + } + + public void preInstantiateSingletons() throws Exception { + for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext(); ) { + String beanName = (String) it.next(); + getBean(beanName); + } + } + + protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception { + Object bean = createBeanInstance(beanDefinition); + beanDefinition.setBean(bean); + applyPropertyValues(bean, beanDefinition); return bean; - } - - protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception { - return beanDefinition.getBeanClass().newInstance(); - } - - public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception { - beanDefinitionMap.put(name, beanDefinition); - beanDefinitionNames.add(name); - } - - public void preInstantiateSingletons() throws Exception { - for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) { - String beanName = (String) it.next(); - getBean(beanName); - } - } - - protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception { - Object bean = createBeanInstance(beanDefinition); - beanDefinition.setBean(bean); - applyPropertyValues(bean, beanDefinition); - return bean; - } - - protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exception { - - } - - public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) throws Exception { - this.beanPostProcessors.add(beanPostProcessor); - } - - // 所有的bean都是从beanDefinition中取出来的, - public List getBeansForType(Class type) throws Exception { - List beans = new ArrayList(); - for (String beanDefinitionName : beanDefinitionNames) { - if (type.isAssignableFrom(beanDefinitionMap.get(beanDefinitionName).getBeanClass())) { - beans.add(getBean(beanDefinitionName)); - } - } - return beans; - } + } + + protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exception { + + } + + public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) throws Exception { + this.beanPostProcessors.add(beanPostProcessor); + } + + // 所有的bean都是从beanDefinition中取出来的, + public List getBeansForType(Class type) throws Exception { + List beans = new ArrayList(); + for (String beanDefinitionName : beanDefinitionNames) { + if (type.isAssignableFrom(beanDefinitionMap.get(beanDefinitionName).getBeanClass())) { + beans.add(getBean(beanDefinitionName)); + } + } + return beans; + } } diff --git a/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java b/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java index 294a22e..d44c0c3 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java +++ b/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java @@ -20,6 +20,11 @@ protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Excep if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(this); } + applyPropertyValueForSetter(bean, mbd); + applyPropertyValuesForField(bean); + } + + private void applyPropertyValueForSetter(Object bean, BeanDefinition mbd) throws Exception { for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) { Object value = propertyValue.getValue(); if (value instanceof BeanReference) { @@ -40,6 +45,9 @@ protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Excep declaredField.set(bean, value); } } + } + + private void applyPropertyValuesForField(Object bean) throws Exception { for (Field field : bean.getClass().getDeclaredFields()) { if (field.isAnnotationPresent(AutoWired.class)) { field.setAccessible(true); @@ -51,4 +59,5 @@ protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Excep } } } + } diff --git a/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java b/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java index 961de9b..9c0a291 100644 --- a/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java +++ b/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java @@ -1,7 +1,10 @@ package us.codecraft.tinyioc.context; +import us.codecraft.tinyioc.beans.BeanDefinition; import us.codecraft.tinyioc.beans.BeanPostProcessor; import us.codecraft.tinyioc.beans.factory.AbstractBeanFactory; +import us.codecraft.tinyioc.message.MessageHandlerHolder; +import us.codecraft.tinyioc.message.MessageHandlerInvocation; import java.util.List; @@ -11,6 +14,8 @@ public abstract class AbstractApplicationContext implements ApplicationContext { protected AbstractBeanFactory beanFactory; + private MessageHandlerHolder messageHandlerHolder = new MessageHandlerHolder(); + public AbstractApplicationContext(AbstractBeanFactory beanFactory) { this.beanFactory = beanFactory; } @@ -18,9 +23,21 @@ public AbstractApplicationContext(AbstractBeanFactory beanFactory) { public void refresh() throws Exception { loadBeanDefinitions(beanFactory); registerBeanPostProcessors(beanFactory); + //消息处理者handler 扫描所有的bean 对方法上有EventListener注解的 + beanFactory.addBeanPostProcessor(messageHandlerHolder); + //将自身注入进bean容器 + registerSelf(); onRefresh(); } + private void registerSelf() throws Exception { + BeanDefinition self = new BeanDefinition(); + self.setBeanClassName(this.getClass().getName()); + self.setBeanClass(this.getClass()); + self.setBean(this); + beanFactory.registerBeanDefinition("applicationContext", self); + } + protected abstract void loadBeanDefinitions(AbstractBeanFactory beanFactory) throws Exception; protected void registerBeanPostProcessors(AbstractBeanFactory beanFactory) throws Exception { @@ -38,4 +55,18 @@ protected void onRefresh() throws Exception { public Object getBean(String name) throws Exception { return beanFactory.getBean(name); } + + + @Override + public void publishEvent(Object object) { + for (MessageHandlerInvocation messageHandlerInvocation : messageHandlerHolder.getMessageHandlers()) { + if (messageHandlerInvocation.getParameterType().getType().isInstance(object)) { + try { + messageHandlerInvocation.handleMessage(object); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + } } diff --git a/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java b/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java index 191fbf7..692d78b 100644 --- a/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java +++ b/src/main/java/us/codecraft/tinyioc/context/ClassPathXmlApplicationContext.java @@ -5,8 +5,6 @@ import us.codecraft.tinyioc.beans.factory.AutowireCapableBeanFactory; import us.codecraft.tinyioc.beans.io.ResourceLoader; import us.codecraft.tinyioc.beans.xml.XmlBeanDefinitionReader; -import us.codecraft.tinyioc.message.MessageHandlerHolder; -import us.codecraft.tinyioc.message.MessageHandlerInvocation; import java.util.Map; @@ -17,7 +15,6 @@ public class ClassPathXmlApplicationContext extends AbstractApplicationContext { private String configLocation; - private MessageHandlerHolder messageHandlerHolder = new MessageHandlerHolder(); public ClassPathXmlApplicationContext(String configLocation) throws Exception { this(configLocation, new AutowireCapableBeanFactory()); @@ -36,30 +33,6 @@ protected void loadBeanDefinitions(AbstractBeanFactory beanFactory) throws Excep for (Map.Entry beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) { beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue()); } - //将自身注入进bean容器 - registerSelf(); - //消息处理者handler 扫描所有的bean 对方法上有EventListener注解的 - beanFactory.addBeanPostProcessor(messageHandlerHolder); } - private void registerSelf() throws Exception { - BeanDefinition self = new BeanDefinition(); - self.setBeanClassName(this.getClass().getName()); - self.setBeanClass(this.getClass()); - self.setBean(this); - beanFactory.registerBeanDefinition("applicationContext", self); - } - - @Override - public void publishEvent(Object object) { - for (MessageHandlerInvocation messageHandlerInvocation : messageHandlerHolder.getMessageHandlers()) { - if (messageHandlerInvocation.getParameterType().getType().isInstance(object)) { - try { - messageHandlerInvocation.handleMessage(object); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - } } diff --git a/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java b/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java index b59b228..5d949b8 100644 --- a/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java +++ b/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java @@ -1,7 +1,7 @@ package us.codecraft.tinyioc.message; /** - * @author 邓凤麒 + * @author winters * 创建时间:13/03/2018 15:47 * 创建原因: **/ diff --git a/src/main/java/us/codecraft/tinyioc/message/EventListener.java b/src/main/java/us/codecraft/tinyioc/message/EventListener.java index 8464a99..2325f9d 100644 --- a/src/main/java/us/codecraft/tinyioc/message/EventListener.java +++ b/src/main/java/us/codecraft/tinyioc/message/EventListener.java @@ -8,7 +8,7 @@ import java.lang.annotation.Target; /** - * @author 邓凤麒 + * @author winters * 创建时间:13/03/2018 15:52 * 创建原因: **/ diff --git a/src/main/java/us/codecraft/tinyioc/message/Message.java b/src/main/java/us/codecraft/tinyioc/message/Message.java index 24d493d..0cbdacf 100644 --- a/src/main/java/us/codecraft/tinyioc/message/Message.java +++ b/src/main/java/us/codecraft/tinyioc/message/Message.java @@ -4,7 +4,7 @@ import lombok.Data; /** - * @author 邓凤麒 + * @author winters * 创建时间:13/03/2018 16:22 * 创建原因: **/ diff --git a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java index 6f95219..e499b11 100644 --- a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java +++ b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java @@ -7,7 +7,7 @@ import java.util.List; /** - * @author 邓凤麒 + * @author winters * 创建时间:13/03/2018 15:51 * 创建原因: **/ diff --git a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java index f0f5d50..21aa273 100644 --- a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java +++ b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerInvocation.java @@ -5,7 +5,7 @@ import java.lang.reflect.Parameter; /** - * @author 邓凤麒 + * @author winters * 创建时间:13/03/2018 15:57 * 创建原因: **/ diff --git a/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java b/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java index dff7a58..b70f8e2 100644 --- a/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java +++ b/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java @@ -13,12 +13,17 @@ public class HelloWorldServiceImpl implements HelloWorldService { private String text; - private OutputService outputService; @AutoWired private ApplicationEventPublisher applicationEventPublisher; + @AutoWired + public HelloWorldServiceImpl(OutputService outputService, ApplicationEventPublisher applicationEventPublisher) { + this.outputService = outputService; + this.applicationEventPublisher = applicationEventPublisher; + } + @Override public void helloWorld() { outputService.output(text); From 64b086fa48a9f02f09164ca3ae84a1d1b44fbc5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=93=E5=87=A4=E9=BA=92?= Date: Sat, 24 Mar 2018 19:26:35 +0800 Subject: [PATCH 4/6] add ignore iml --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index af515ad..4e95151 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea target/ +tiny-spring.iml From 9e7b6c012215fb354fa6b4ec6f8a70c3d8363ef9 Mon Sep 17 00:00:00 2001 From: winters Date: Fri, 6 Apr 2018 08:17:38 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java | 8 ++++++-- .../java/us/codecraft/tinyioc/aop/BeanFactoryAware.java | 5 +++++ .../tinyioc/beans/factory/AbstractBeanFactory.java | 5 +++++ .../tinyioc/context/AbstractApplicationContext.java | 3 +++ .../codecraft/tinyioc/message/MessageHandlerHolder.java | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java b/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java index c24695c..d82e1af 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java +++ b/src/main/java/us/codecraft/tinyioc/aop/AspectJAwareAdvisorAutoProxyCreator.java @@ -30,9 +30,12 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw if (bean instanceof MethodInterceptor) { return bean; } - List advisors = beanFactory - .getBeansForType(AspectJExpressionPointcutAdvisor.class); + /* + 此处获得advisor,由advisor来负责判断当前传入的bean是否需要被增强 + */ + List advisors = beanFactory.getBeansForType(AspectJExpressionPointcutAdvisor.class); for (AspectJExpressionPointcutAdvisor advisor : advisors) { + //advisor匹配 if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) { ProxyFactory advisedSupport = new ProxyFactory(); advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice()); @@ -49,6 +52,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw } //初始化的时候 注入beanFactory + //在beanPostProcessor接口回调的时候 使用beanFactory的引用 @Override public void setBeanFactory(BeanFactory beanFactory) throws Exception { this.beanFactory = (AbstractBeanFactory) beanFactory; diff --git a/src/main/java/us/codecraft/tinyioc/aop/BeanFactoryAware.java b/src/main/java/us/codecraft/tinyioc/aop/BeanFactoryAware.java index e29a8c6..d0da8b4 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/BeanFactoryAware.java +++ b/src/main/java/us/codecraft/tinyioc/aop/BeanFactoryAware.java @@ -5,6 +5,11 @@ /** * @author yihua.huang@dianping.com */ + +/* + 此接口主要的目的,是将BeanFactory的引用 注入进一些特殊的bean中,例如 BeanProcessor的实现 + AspectJAwareAdvisorAutoProxyCreator 需要处理一些AOP相关的代理 + */ public interface BeanFactoryAware { void setBeanFactory(BeanFactory beanFactory) throws Exception; diff --git a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java index b1fc8ee..f219fe2 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java +++ b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java @@ -35,6 +35,10 @@ public Object getBean(String name) throws Exception { return bean; } + /* + 此方法十分重要, 在初始化bean的同时,把所有的bean + 都传入进实现了BeanPostProcessor接口的实现类中,更新对象为process增强后的bean + */ protected Object initializeBean(Object bean, String name) throws Exception { for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { //初始化之前 @@ -45,6 +49,7 @@ protected Object initializeBean(Object bean, String name) throws Exception { for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { //初始化之后 对bean进行增强 原始的bean 被代理bean 的引用持有 Object preBean = bean; + bean = beanPostProcessor.postProcessAfterInitialization(bean, name); //断言 增强后的 bean 是原始bean的父类 assert preBean.getClass().isAssignableFrom(bean.getClass()); diff --git a/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java b/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java index 9c0a291..80a7070 100644 --- a/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java +++ b/src/main/java/us/codecraft/tinyioc/context/AbstractApplicationContext.java @@ -22,6 +22,7 @@ public AbstractApplicationContext(AbstractBeanFactory beanFactory) { public void refresh() throws Exception { loadBeanDefinitions(beanFactory); + //抽象应用上下文 向beanFactory注册beanPostProcessor registerBeanPostProcessors(beanFactory); //消息处理者handler 扫描所有的bean 对方法上有EventListener注解的 beanFactory.addBeanPostProcessor(messageHandlerHolder); @@ -40,8 +41,10 @@ private void registerSelf() throws Exception { protected abstract void loadBeanDefinitions(AbstractBeanFactory beanFactory) throws Exception; + //从beanFactory中 拿出所有的 BeanPostProcessor接口的实现类 protected void registerBeanPostProcessors(AbstractBeanFactory beanFactory) throws Exception { List beanPostProcessors = beanFactory.getBeansForType(BeanPostProcessor.class); + //全部加入到beanFactory的 beanPostProcessors 引用中去 for (Object beanPostProcessor : beanPostProcessors) { beanFactory.addBeanPostProcessor((BeanPostProcessor) beanPostProcessor); } diff --git a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java index e499b11..c702ea7 100644 --- a/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java +++ b/src/main/java/us/codecraft/tinyioc/message/MessageHandlerHolder.java @@ -11,6 +11,7 @@ * 创建时间:13/03/2018 15:51 * 创建原因: **/ +//实现了 beanPostProcessor接口 public class MessageHandlerHolder implements BeanPostProcessor { private List messageHandlers = new ArrayList<>(); From 226b2c7f34b67a447181299daa58fcf6f8ac96bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=93=E5=87=A4=E9=BA=92?= Date: Sat, 7 Apr 2018 15:49:12 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 ++ .../codecraft/tinyioc/aop/JdkDynamicAopProxy.java | 1 + .../us/codecraft/tinyioc/beans/AutoWired.java | 3 ++- .../beans/factory/AbstractBeanFactory.java | 15 ++++++++++++++- .../beans/factory/AutowireCapableBeanFactory.java | 4 +++- .../message/ApplicationEventPublisher.java | 2 +- .../us/codecraft/tinyioc/BeanFactoryTest.java | 3 ++- .../codecraft/tinyioc/HelloWorldServiceImpl.java | 6 ++++-- 8 files changed, 29 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index ae95495..3eadfe3 100644 --- a/pom.xml +++ b/pom.xml @@ -90,6 +90,7 @@ + diff --git a/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java b/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java index 01738c5..bf28610 100644 --- a/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java +++ b/src/main/java/us/codecraft/tinyioc/aop/JdkDynamicAopProxy.java @@ -13,6 +13,7 @@ */ public class JdkDynamicAopProxy extends AbstractAopProxy implements InvocationHandler { + // advisedSupport 调用实际方法前 调用hook方法 , 标明需要 拦截哪些方法 public JdkDynamicAopProxy(AdvisedSupport advised) { super(advised); } diff --git a/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java b/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java index 83a3b85..d6e3f28 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java +++ b/src/main/java/us/codecraft/tinyioc/beans/AutoWired.java @@ -13,7 +13,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -//此处Autowired 只适用在字段上 +//此处Autowired 只适用在字段注入 跟 构造注入 @Target({ElementType.FIELD,ElementType.CONSTRUCTOR}) @Retention(RetentionPolicy.RUNTIME) @@ -21,4 +21,5 @@ @Documented public @interface AutoWired { + boolean required() default true; } diff --git a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java index f219fe2..b72983d 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java +++ b/src/main/java/us/codecraft/tinyioc/beans/factory/AbstractBeanFactory.java @@ -28,8 +28,14 @@ public Object getBean(String name) throws Exception { } Object bean = beanDefinition.getBean(); if (bean == null) { + // do create bean bean = doCreateBean(beanDefinition); + // init bean = initializeBean(bean, name); + + // 初始化后获得的bean 有可能是增强实现 + // 所以在beanDefinition中更新为增强的bean + beanDefinition.setBean(bean); } return bean; @@ -40,6 +46,8 @@ public Object getBean(String name) throws Exception { 都传入进实现了BeanPostProcessor接口的实现类中,更新对象为process增强后的bean */ protected Object initializeBean(Object bean, String name) throws Exception { + // 初始化的时候 调用BeanPostProcessor + for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { //初始化之前 bean = beanPostProcessor.postProcessBeforeInitialization(bean, name); @@ -60,16 +68,21 @@ protected Object initializeBean(Object bean, String name) throws Exception { protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception { Constructor[] constructors = beanDefinition.getBeanClass().getConstructors(); for (int i = 0; i < constructors.length; i++) { - if (constructors[i].isAnnotationPresent(AutoWired.class)) { + if (constructors[i].isAnnotationPresent(AutoWired.class) && ((AutoWired) constructors[i].getAnnotation(AutoWired.class)).required() + ) { List objs = new ArrayList(); for (Class clazz : constructors[i].getParameterTypes()) { List beansForType = getBeansForType(clazz); if (beansForType.size() == 1) { objs.add(beansForType.get(0)); + } else { + //存在两个及其以上的候选注入bean TODO 实现Qualifier } } if (objs.size() == constructors[i].getParameterCount()) { return constructors[i].newInstance(objs.toArray()); + } else { + throw new RuntimeException("构造注入缺少指定类型的bean"); } } } diff --git a/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java b/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java index d44c0c3..78ae128 100644 --- a/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java +++ b/src/main/java/us/codecraft/tinyioc/beans/factory/AutowireCapableBeanFactory.java @@ -49,9 +49,11 @@ private void applyPropertyValueForSetter(Object bean, BeanDefinition mbd) throws private void applyPropertyValuesForField(Object bean) throws Exception { for (Field field : bean.getClass().getDeclaredFields()) { - if (field.isAnnotationPresent(AutoWired.class)) { + if (field.isAnnotationPresent(AutoWired.class) && field.getAnnotation(AutoWired.class).required()) { field.setAccessible(true); List beansForType = getBeansForType(field.getType()); + + //todo implement qualifier if (beansForType.size() != 1) { throw new RuntimeException("可选注入类型 超过1个, 或者没有可选注入类型"); } diff --git a/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java b/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java index 5d949b8..22c21bb 100644 --- a/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java +++ b/src/main/java/us/codecraft/tinyioc/message/ApplicationEventPublisher.java @@ -8,7 +8,7 @@ public interface ApplicationEventPublisher { /** * 发布消息 - * @param object + * @param object nothing */ void publishEvent(Object object); } diff --git a/src/test/java/us/codecraft/tinyioc/BeanFactoryTest.java b/src/test/java/us/codecraft/tinyioc/BeanFactoryTest.java index dfae7c5..8e701b7 100644 --- a/src/test/java/us/codecraft/tinyioc/BeanFactoryTest.java +++ b/src/test/java/us/codecraft/tinyioc/BeanFactoryTest.java @@ -1,6 +1,5 @@ package us.codecraft.tinyioc; -import java.util.Map; import org.junit.Test; import us.codecraft.tinyioc.beans.BeanDefinition; import us.codecraft.tinyioc.beans.factory.AbstractBeanFactory; @@ -8,6 +7,8 @@ import us.codecraft.tinyioc.beans.io.ResourceLoader; import us.codecraft.tinyioc.beans.xml.XmlBeanDefinitionReader; +import java.util.Map; + /** * @author yihua.huang@dianping.com */ diff --git a/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java b/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java index b70f8e2..adfa553 100644 --- a/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java +++ b/src/test/java/us/codecraft/tinyioc/HelloWorldServiceImpl.java @@ -1,6 +1,7 @@ package us.codecraft.tinyioc; import lombok.Data; +import lombok.NoArgsConstructor; import us.codecraft.tinyioc.beans.AutoWired; import us.codecraft.tinyioc.message.ApplicationEventPublisher; import us.codecraft.tinyioc.message.EventListener; @@ -10,15 +11,16 @@ * @author yihua.huang@dianping.com */ @Data +@NoArgsConstructor public class HelloWorldServiceImpl implements HelloWorldService { private String text; private OutputService outputService; - @AutoWired + @AutoWired(required = false) private ApplicationEventPublisher applicationEventPublisher; - @AutoWired + @AutoWired(required = false) public HelloWorldServiceImpl(OutputService outputService, ApplicationEventPublisher applicationEventPublisher) { this.outputService = outputService; this.applicationEventPublisher = applicationEventPublisher;