├── .gitignore ├── README.md ├── pom.xml └── src ├── main ├── java │ ├── aop │ │ ├── AfterReturningAdvice.java │ │ ├── AopProxy.java │ │ ├── CglibAopPorxy.java │ │ ├── DelegatingIntroductionInterceptor.java │ │ ├── JdkDynamicAopProxy.java │ │ ├── MethodBeforeAdvice.java │ │ ├── ProxyConfig.java │ │ ├── ProxyFactory.java │ │ ├── ProxyFactoryBean.java │ │ ├── ReflectiveMethodInvocation.java │ │ └── adapter │ │ │ ├── AfterReturningAdviceInterceptor.java │ │ │ └── MethodBeforeAdviceInterceptor.java │ ├── bean │ │ ├── BeanDefinition.java │ │ ├── ConstructorValue.java │ │ ├── ConstructorValues.java │ │ ├── PropertyValue.java │ │ └── PropertyValues.java │ ├── context │ │ ├── AbstractApplicationContext.java │ │ ├── ApplicationContext.java │ │ └── ClassPathXmlApplicationContext.java │ ├── entity │ │ ├── HelloWorldA.java │ │ ├── HelloWorldB.java │ │ └── HelloWorldService.java │ ├── exception │ │ └── BeanCurrentlyInCreationException.java │ ├── factory │ │ ├── AbstractBeanFactory.java │ │ ├── AutowireCapableBeanFactory.java │ │ ├── Aware.java │ │ ├── BeanFactory.java │ │ ├── BeanFactoryAware.java │ │ ├── FactoryBean.java │ │ └── XMLBeanFactory.java │ ├── reader │ │ └── XMLBeanDefinitionReader.java │ └── resource │ │ └── ClassPathResource.java └── resources │ └── beanFactoryTest.xml └── test ├── java ├── SpringAopTest.java ├── SpringApplicationContextTest.java ├── SpringTest.java ├── aopAdvice │ ├── PerformerAfterAdvice.java │ ├── PerformerAroundAdvice.java │ └── PerformerBeforeAdvice.java ├── aopEntity │ ├── Apology.java │ ├── GreetingIntroAdvice.java │ ├── NiceJudge.java │ ├── Performer.java │ └── Singer.java └── exception │ └── PerformanceException.java └── resources ├── DelegatingIntroductionInterceptor.xml ├── ProxyFactoryBean.xml └── spring-idol.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | # Compiled class file 4 | *.class 5 | .idea/ 6 | *.iml 7 | 8 | # Log file 9 | *.log 10 | 11 | # BlueJ files 12 | *.ctxt 13 | 14 | # Mobile Tools for Java (J2ME) 15 | .mtj.tmp/ 16 | 17 | # Package Files # 18 | *.jar 19 | *.war 20 | *.nar 21 | *.ear 22 | *.zip 23 | *.tar.gz 24 | *.rar 25 | 26 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 27 | hs_err_pid* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny-spring 2 | 本项目是一个精简版的spring,通过自己实现一遍spring来理解spring框架的精华。 3 | 4 | ## IOC计划 5 | * [x] **最基本的容器:** 使用BeanFactory来获取bean,使用BeanDefinition来封装bean对象。 6 | * [x] **将bean创建放入工厂:** 设置beanClass的名称,通过反射来创建bean。 7 | * [x] **为bean注入属性:** 使用PropertyValue对象来存储bean的属性信息,使用ConstructorValue来存储构造器属性信息。 8 | * [x] **读取xml配置来初始化bean:** 引用XMLBeanDefinitionReader来读取xml中的信息,并将xml中的信息转化为BeanDefinition和PropertyValue 9 | * [x] **实现ApplicationContext:** 自动初始化所有bean 10 | 11 | 12 | ## AOP计划 13 | aop的实现遵守的[aop联盟](http://aopalliance.sourceforge.net/)的规定,所以需要先引入[aopalliance.jar](https://mvnrepository.com/artifact/aopalliance/aopalliance)。 14 | * [x] **实现简单版的jdk和cglib的动态代理:** [jdk动态代理](https://blog.csdn.net/wangdong5678999/article/details/72801623)通过InvocationHandler实现,缺点是必须需要代理的类必须实现了接口才能被jdk代理;[CGLIB](https://github.com/cglib/cglib)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成,CGLIB通过继承方式实现代理。 15 | * [x] **通过ProxyFactoryBean来实现aop和ioc的结合。** 16 | 1. 实现BeanFactoryAware接口,将beanFactory注入到ProxyFactoryBean中 17 | 2. 实现FactoryBean,获取代理对象 18 | * [x] **实现引入:** 对类的功能增强,实现原来类未实现的接口 19 | * [ ] **实现切面功能:** 即通知点和通知的结合 20 | * [ ] **实现aop自动代理,扫描 Bean 名称** 21 | * [ ] **接入aspectj,实现注解式配置切面** 22 | 23 | ## 收获 24 | 1. 对java中的一些概念有了更深入的理解,比如java内省、[javaBean](https://blog.csdn.net/zhuwenchao90/article/details/54893253) 等。 25 | 2. 阅读源码能力得到增强,现在读spring的源码,再也不会迷路了。 26 | 3. 当自己写好一个功能后,再去看看spring是怎么实现的,会有种恍然大悟的感觉! 27 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.dong 8 | tiny-spring 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 8 17 | 8 18 | 19 | 20 | 21 | 22 | 23 | 24 | junit 25 | junit 26 | 4.12 27 | test 28 | 29 | 30 | org.dom4j 31 | dom4j 32 | 2.1.1 33 | 34 | 35 | org.projectlombok 36 | lombok 37 | 1.18.4 38 | provided 39 | 40 | 41 | 42 | aopalliance 43 | aopalliance 44 | 1.0 45 | 46 | 47 | cglib 48 | cglib 49 | 2.2.2 50 | 51 | 52 | commons-beanutils 53 | commons-beanutils 54 | 1.9.3 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/aop/AfterReturningAdvice.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import org.aopalliance.aop.Advice; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | public interface AfterReturningAdvice extends Advice { 8 | void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/aop/AopProxy.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | public interface AopProxy { 4 | 5 | /** 6 | * Create a new proxy object. 7 | *

Uses the AopProxy's default class loader (if necessary for proxy creation): 8 | * usually, the thread context class loader. 9 | * @return the new proxy object (never {@code null}) 10 | * @see Thread#getContextClassLoader() 11 | */ 12 | Object getProxy(); 13 | 14 | /** 15 | * Create a new proxy object. 16 | *

Uses the given class loader (if necessary for proxy creation). 17 | * {@code null} will simply be passed down and thus lead to the low-level 18 | * proxy facility's default, which is usually different from the default chosen 19 | * by the AopProxy implementation's {@link #getProxy()} method. 20 | * @param classLoader the class loader to create the proxy with 21 | * (or {@code null} for the low-level proxy facility's default) 22 | * @return the new proxy object (never {@code null}) 23 | */ 24 | Object getProxy(ClassLoader classLoader); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/aop/CglibAopPorxy.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import lombok.Data; 4 | import net.sf.cglib.proxy.Enhancer; 5 | import net.sf.cglib.proxy.MethodInterceptor; 6 | import net.sf.cglib.proxy.MethodProxy; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | @Data 11 | public class CglibAopPorxy implements MethodInterceptor, AopProxy { 12 | private ProxyFactory proxyFactory; 13 | 14 | public CglibAopPorxy(ProxyFactory proxyFactory) { 15 | this.proxyFactory = proxyFactory; 16 | } 17 | 18 | @Override 19 | public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 20 | return new ReflectiveMethodInvocation(proxyFactory.getProxy(),proxyFactory.getTarget(),method,args,proxyFactory.getTarget().getClass(),proxyFactory.getMethodInterceptors()).proceed(); 21 | } 22 | 23 | @Override 24 | public Object getProxy() { 25 | return Enhancer.create(proxyFactory.getTarget().getClass(), proxyFactory.getInterfaces(),this); 26 | } 27 | 28 | @Override 29 | public Object getProxy(ClassLoader classLoader) { 30 | return Enhancer.create(proxyFactory.getTarget().getClass(), this); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/aop/DelegatingIntroductionInterceptor.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | 6 | import java.lang.reflect.Method; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | /** 12 | * 引入的实现 13 | */ 14 | public class DelegatingIntroductionInterceptor implements MethodInterceptor { 15 | 16 | 17 | private Object delegate; 18 | private List supportInterfaces = new ArrayList<>(); 19 | private List supportMethods = new ArrayList<>(); 20 | 21 | 22 | public DelegatingIntroductionInterceptor(Object delegate) { 23 | init(delegate); 24 | } 25 | 26 | public DelegatingIntroductionInterceptor() { 27 | init(this); 28 | } 29 | 30 | private void init(Object delegate) { 31 | this.delegate = delegate; 32 | supportInterfaces = Arrays.asList(delegate.getClass().getInterfaces()); 33 | supportMethods = Arrays.asList(delegate.getClass().getMethods()); 34 | 35 | } 36 | 37 | public Object getDelegate() { 38 | return delegate; 39 | } 40 | 41 | public void setDelegate(Object delegate) { 42 | this.delegate = delegate; 43 | } 44 | 45 | @Override 46 | public Object invoke(MethodInvocation invocation) throws Throwable { 47 | if (supportInterfaces.contains(invocation.getMethod().getDeclaringClass())){ 48 | Method method = invocation.getMethod(); 49 | method.setAccessible(true); 50 | 51 | return method.invoke(delegate, invocation.getArguments()); 52 | } 53 | return invocation.proceed(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/aop/JdkDynamicAopProxy.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Proxy; 6 | 7 | public class JdkDynamicAopProxy implements InvocationHandler,AopProxy { 8 | private ProxyFactory proxyFactory; 9 | 10 | JdkDynamicAopProxy(ProxyFactory proxyFactory) { 11 | this.proxyFactory = proxyFactory; 12 | } 13 | 14 | @Override 15 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 16 | return new ReflectiveMethodInvocation(proxyFactory.getTarget(),proxyFactory.getTarget(),method,args,proxyFactory.getTarget().getClass(),proxyFactory.getMethodInterceptors()).proceed(); 17 | } 18 | 19 | @Override 20 | public Object getProxy() { 21 | return Proxy.newProxyInstance(proxyFactory.getTarget().getClass().getClassLoader(),proxyFactory.getTarget().getClass().getInterfaces(),this); 22 | 23 | } 24 | 25 | @Override 26 | public Object getProxy(ClassLoader classLoader) { 27 | return Proxy.newProxyInstance(classLoader,proxyFactory.getTarget().getClass().getInterfaces(),this); 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/aop/MethodBeforeAdvice.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import org.aopalliance.aop.Advice; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | /** 8 | * aop前置增强接口 9 | */ 10 | public interface MethodBeforeAdvice extends Advice { 11 | void before(Method method, Object[] args, Object target) throws Throwable; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/aop/ProxyConfig.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import lombok.Data; 4 | import org.aopalliance.aop.Advice; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class ProxyConfig { 11 | List beforeAdvices = new ArrayList<>(); 12 | List afterReturningAdvices = new ArrayList<>(); 13 | List aroundAdvices = new ArrayList<>(); 14 | 15 | Object target; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/aop/ProxyFactory.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import aop.adapter.AfterReturningAdviceInterceptor; 4 | import aop.adapter.MethodBeforeAdviceInterceptor; 5 | import lombok.Data; 6 | import org.aopalliance.aop.Advice; 7 | import org.aopalliance.intercept.MethodInterceptor; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @Data 13 | public class ProxyFactory{ 14 | // List beforeAdvices = new ArrayList<>(); 15 | // List afterReturningAdvices = new ArrayList<>(); 16 | // List aroundAdvices = new ArrayList<>(); 17 | 18 | List methodInterceptors = new ArrayList<>(); 19 | Object target; 20 | Class[] interfaces; 21 | boolean proxyTargetClass = false; 22 | 23 | public Object getProxy(){ 24 | return createAopProxy().getProxy(); 25 | } 26 | 27 | /** 28 | * 若是代理接口,使用jdk代理,如果没有接口,通过cglib代理 29 | * @return 30 | */ 31 | private AopProxy createAopProxy() { 32 | if (proxyTargetClass) { 33 | return new CglibAopPorxy(this); 34 | } 35 | if (target.getClass().isInterface() || target.getClass().getInterfaces().length != 0){ 36 | return new JdkDynamicAopProxy(this); 37 | } 38 | return new CglibAopPorxy(this); 39 | } 40 | 41 | public void addAdvice(Advice advice){ 42 | if (advice instanceof MethodBeforeAdvice){ 43 | methodInterceptors.add(new MethodBeforeAdviceInterceptor((MethodBeforeAdvice)advice)); 44 | } 45 | if (advice instanceof AfterReturningAdvice){ 46 | methodInterceptors.add(new AfterReturningAdviceInterceptor((AfterReturningAdvice)advice)); 47 | } 48 | 49 | if (advice instanceof MethodInterceptor){ 50 | methodInterceptors.add((MethodInterceptor)advice); 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/aop/ProxyFactoryBean.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import factory.BeanFactory; 4 | import factory.BeanFactoryAware; 5 | import factory.FactoryBean; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import org.aopalliance.aop.Advice; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | public class ProxyFactoryBean extends ProxyFactory implements FactoryBean, BeanFactoryAware { 13 | private boolean singleton = true; 14 | private BeanFactory beanFactory; 15 | private String afterReturningAdvice; 16 | private String beforeAdvice; 17 | private String methodInterceptor; 18 | 19 | @Override 20 | public Object getObject() { 21 | initialInterceptorChain(); 22 | return super.getProxy(); 23 | } 24 | 25 | private void initialInterceptorChain() { 26 | addAdvice((Advice) beanFactory.getBean(afterReturningAdvice)); 27 | addAdvice((Advice) beanFactory.getBean(beforeAdvice)); 28 | addAdvice((Advice) beanFactory.getBean(methodInterceptor)); 29 | // interceptorNames.forEach(interceptorNames -> addAdvice((Advice) beanFactory.getBean(interceptorNames))); 30 | } 31 | 32 | @Override 33 | public Class getObjectType() { 34 | return super.getClass(); 35 | } 36 | 37 | @Override 38 | public boolean isSingleton() { 39 | return singleton; 40 | } 41 | 42 | 43 | @Override 44 | public void setBeanFactory(BeanFactory beanFactory) { 45 | this.beanFactory = beanFactory; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/aop/ReflectiveMethodInvocation.java: -------------------------------------------------------------------------------- 1 | package aop; 2 | 3 | import lombok.Data; 4 | import org.aopalliance.intercept.MethodInterceptor; 5 | import org.aopalliance.intercept.MethodInvocation; 6 | 7 | import java.lang.reflect.AccessibleObject; 8 | import java.lang.reflect.Method; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | @Data 13 | public class ReflectiveMethodInvocation implements MethodInvocation { 14 | 15 | protected final Object proxy; 16 | 17 | protected final Object target; 18 | 19 | /** 20 | * 要调用的方法 21 | */ 22 | protected final Method method; 23 | 24 | /** 25 | * 方法参数 26 | */ 27 | protected Object[] arguments; 28 | 29 | /** 30 | * 31 | */ 32 | private final Class targetClass; 33 | 34 | private Map userAttributes; 35 | 36 | /** 37 | * 拦截器的list 38 | */ 39 | protected final List interceptorsAndDynamicMethodMatchers; 40 | 41 | 42 | private int currentInterceptorIndex = -1; 43 | 44 | public ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] arguments, Class targetClass, List interceptorsAndDynamicMethodMatchers) { 45 | this.proxy = proxy; 46 | this.target = target; 47 | this.method = method; 48 | this.arguments = arguments; 49 | this.targetClass = targetClass; 50 | this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; 51 | } 52 | 53 | @Override 54 | public Object proceed() throws Throwable { 55 | //没有拦截器,直接调用方法 56 | if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 57 | method.setAccessible(true); 58 | 59 | return method.invoke(target, arguments); 60 | } 61 | Object interceptorOrInterceptionAdvice = 62 | this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); 63 | return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 64 | } 65 | 66 | @Override 67 | public Object getThis() { 68 | return this.target; 69 | } 70 | 71 | @Override 72 | public AccessibleObject getStaticPart() { 73 | return this.method; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/aop/adapter/AfterReturningAdviceInterceptor.java: -------------------------------------------------------------------------------- 1 | package aop.adapter; 2 | 3 | import aop.AfterReturningAdvice; 4 | import org.aopalliance.aop.Advice; 5 | import org.aopalliance.intercept.MethodInterceptor; 6 | import org.aopalliance.intercept.MethodInvocation; 7 | 8 | import java.io.Serializable; 9 | 10 | public class AfterReturningAdviceInterceptor implements MethodInterceptor, Advice, Serializable { 11 | 12 | private final AfterReturningAdvice advice; 13 | 14 | /** 15 | * Create a new AfterReturningAdviceInterceptor for the given advice. 16 | * @param advice the AfterReturningAdvice to wrap 17 | */ 18 | public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) { 19 | this.advice = advice; 20 | } 21 | 22 | public Object invoke(MethodInvocation mi) throws Throwable { 23 | Object retVal = mi.proceed(); 24 | this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); 25 | return retVal; 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/aop/adapter/MethodBeforeAdviceInterceptor.java: -------------------------------------------------------------------------------- 1 | package aop.adapter; 2 | 3 | import aop.MethodBeforeAdvice; 4 | import org.aopalliance.aop.Advice; 5 | import org.aopalliance.intercept.MethodInterceptor; 6 | import org.aopalliance.intercept.MethodInvocation; 7 | 8 | import java.io.Serializable; 9 | 10 | public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Advice, Serializable { 11 | private final MethodBeforeAdvice advice; 12 | 13 | public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { 14 | this.advice = advice; 15 | } 16 | 17 | @Override 18 | public Object invoke(MethodInvocation invocation) throws Throwable { 19 | advice.before(invocation.getMethod(),invocation.getArguments(),invocation.getThis()); 20 | return invocation.proceed(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/bean/BeanDefinition.java: -------------------------------------------------------------------------------- 1 | package bean; 2 | 3 | import factory.BeanFactory; 4 | import factory.BeanFactoryAware; 5 | import factory.FactoryBean; 6 | import lombok.Data; 7 | import org.apache.commons.beanutils.BeanUtils; 8 | 9 | import java.lang.reflect.Constructor; 10 | import java.lang.reflect.Field; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.HashSet; 15 | import java.util.List; 16 | 17 | @Data 18 | public class BeanDefinition { 19 | private Object object; 20 | private String beanClassName; 21 | private String beanId; 22 | private PropertyValues propertyValues; 23 | private ConstructorValues constructorValues; 24 | private BeanFactory beanFactory; 25 | 26 | private List dependOnClassList = new ArrayList<>(); 27 | 28 | public ConstructorValues getConstructorValues() { 29 | return constructorValues; 30 | } 31 | 32 | public void setConstructorValues(ConstructorValues constructorValues) { 33 | this.constructorValues = constructorValues; 34 | } 35 | 36 | public BeanDefinition(Object object) { 37 | this.object = object; 38 | } 39 | 40 | public BeanDefinition() { 41 | } 42 | 43 | public Object getBean(BeanFactory beanFactory) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException { 44 | this.beanFactory = beanFactory; 45 | Class clazz = Class.forName(beanClassName); 46 | Constructor constructor = clazz.getConstructor(getClassArray()); 47 | object = constructor.newInstance(getObjectArray()); 48 | propertyValues.getPropertyValueList().forEach(propertyValue -> { 49 | Object value; 50 | if (propertyValue.getRef() != null) { 51 | value = beanFactory.getBean(propertyValue.getRef()); 52 | }else{ 53 | value = propertyValue.getValue(); 54 | } 55 | try { 56 | BeanUtils.setProperty(object,propertyValue.getField(),value); 57 | // PropertyUtils.setProperty(object, propertyValue.getField(), value); 58 | } catch (IllegalAccessException | InvocationTargetException e) { 59 | e.printStackTrace(); 60 | } 61 | }); 62 | 63 | try { 64 | postProcessBeanFactory(object); 65 | } catch (Exception ignored) { 66 | 67 | } 68 | if (object instanceof FactoryBean) { 69 | return this.beanFactory.getObjectFromFactoryBean((FactoryBean) object); 70 | } 71 | 72 | beanFactory.cacheBean(beanId, object); 73 | 74 | return object; 75 | } 76 | private static Object getPrivateStatic(Class clazz, String f) throws Exception { 77 | try { 78 | Field field = clazz.getDeclaredField(f); 79 | field.setAccessible(true); 80 | return field.get(null); 81 | } 82 | catch (NoSuchFieldException e) { 83 | // Throw a more helpful exception. 84 | throw new NoSuchFieldException( 85 | "Could not find field named '" + f + "' in class '" + clazz + 86 | "'. All fields: " + Arrays.asList(clazz.getDeclaredFields())); 87 | } 88 | } 89 | private void postProcessBeanFactory(Object o) throws Exception { 90 | if (o instanceof BeanFactoryAware){ 91 | ((BeanFactoryAware) o).setBeanFactory(beanFactory); 92 | } 93 | } 94 | 95 | private Class[] getClassArray() { 96 | List classes = new ArrayList<>(); 97 | constructorValues.getConstructorValueList().forEach(constructorValue -> { 98 | if (constructorValue.getRef() != null){ 99 | String className = beanFactory.getBeanType(constructorValue.getRef()); 100 | try { 101 | classes.add(Class.forName(className)); 102 | } catch (ClassNotFoundException e) { 103 | e.printStackTrace(); 104 | } 105 | }else if (constructorValue.getValue() != null){ 106 | classes.add(String.class); 107 | } 108 | }); 109 | return classes.toArray(new Class[constructorValues.getConstructorValueList().size()]); 110 | // return constructorValues.getConstructorValueList().stream().map(constructorValue -> { 111 | // 112 | // }).map(refName-> beanFactory.getBeanType(refName)).map(className -> { 113 | // 114 | // try { 115 | // return Class.forName(className); 116 | // } catch (ClassNotFoundException e) { 117 | // e.printStackTrace(); 118 | // } 119 | // return Collections.EMPTY_LIST; 120 | // }).collect(Collectors.toList()).toArray(new Class[constructorValues.getConstructorValueList().size()]); 121 | } 122 | 123 | private boolean isHasDuplicateData(List list) { 124 | HashSet hashSet = new HashSet<>(list); 125 | 126 | return list.size() != hashSet.size(); 127 | } 128 | 129 | private Object[] getObjectArray(){ 130 | List objects = new ArrayList<>(); 131 | constructorValues.getConstructorValueList().forEach(constructorValue -> { 132 | if (constructorValue.getRef() != null){ 133 | 134 | objects.add(beanFactory.getBean(constructorValue.getRef())); 135 | 136 | }else if (constructorValue.getValue() != null){ 137 | objects.add(constructorValue.getValue()); 138 | } 139 | }); 140 | return objects.toArray(); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/bean/ConstructorValue.java: -------------------------------------------------------------------------------- 1 | package bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | @AllArgsConstructor 7 | @Data 8 | public class ConstructorValue { 9 | private String index; 10 | private String ref; 11 | private String value; 12 | private String name; 13 | } -------------------------------------------------------------------------------- /src/main/java/bean/ConstructorValues.java: -------------------------------------------------------------------------------- 1 | package bean; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ConstructorValues { 7 | private List constructorValueList = new ArrayList<>(); 8 | 9 | public ConstructorValues() { 10 | } 11 | 12 | public List getConstructorValueList() { 13 | return constructorValueList; 14 | } 15 | 16 | public void setConstructorValueList(List constructorValueList) { 17 | this.constructorValueList = constructorValueList; 18 | } 19 | public void addConstructorValue(ConstructorValue constructorValue) { 20 | constructorValueList.add(constructorValue); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/bean/PropertyValue.java: -------------------------------------------------------------------------------- 1 | package bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class PropertyValue { 7 | private String field; 8 | private Object value; 9 | private String ref; 10 | 11 | public PropertyValue(String field, Object value, String ref) { 12 | this.field = field; 13 | this.value = value; 14 | this.ref = ref; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/bean/PropertyValues.java: -------------------------------------------------------------------------------- 1 | package bean; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class PropertyValues { 7 | private List propertyValueList = new ArrayList<>(); 8 | 9 | public void addPropertyValue(PropertyValue propertyValue) { 10 | propertyValueList.add(propertyValue); 11 | } 12 | 13 | public List getPropertyValueList() { 14 | return propertyValueList; 15 | } 16 | 17 | public void setPropertyValueList(List propertyValueList) { 18 | this.propertyValueList = propertyValueList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/context/AbstractApplicationContext.java: -------------------------------------------------------------------------------- 1 | package context; 2 | 3 | import bean.BeanDefinition; 4 | import factory.BeanFactory; 5 | import factory.FactoryBean; 6 | import factory.XMLBeanFactory; 7 | 8 | public class AbstractApplicationContext implements ApplicationContext { 9 | 10 | XMLBeanFactory beanFactory; 11 | 12 | public void setBeanFactory(XMLBeanFactory beanFactory) { 13 | this.beanFactory = beanFactory; 14 | } 15 | 16 | public BeanFactory getBeanFactory() { 17 | return beanFactory; 18 | } 19 | 20 | @Override 21 | public void registerBeanDefinition(String className, BeanDefinition beanDefinition) { 22 | beanFactory.registerBeanDefinition(className,beanDefinition); 23 | } 24 | 25 | @Override 26 | public void cacheBean(String className, Object object) { 27 | beanFactory.cacheBean(className,object); 28 | } 29 | 30 | @Override 31 | public Object getBean(String beanName) { 32 | return beanFactory.getBean(beanName); 33 | } 34 | 35 | @Override 36 | public String getBeanType(String beanId) { 37 | return beanFactory.getBeanType(beanId); 38 | } 39 | 40 | @Override 41 | public Object getObjectFromFactoryBean(FactoryBean object) { 42 | return null; 43 | } 44 | 45 | public void refresh() { 46 | beanFactory.prepareInstanceBeans(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/context/ApplicationContext.java: -------------------------------------------------------------------------------- 1 | package context; 2 | 3 | import factory.BeanFactory; 4 | 5 | public interface ApplicationContext extends BeanFactory { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/context/ClassPathXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | package context; 2 | 3 | import factory.XMLBeanFactory; 4 | import resource.ClassPathResource; 5 | 6 | public class ClassPathXmlApplicationContext extends AbstractApplicationContext { 7 | public ClassPathXmlApplicationContext(String fileName) { 8 | beanFactory = new XMLBeanFactory(new ClassPathResource(fileName)); 9 | refresh(); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/entity/HelloWorldA.java: -------------------------------------------------------------------------------- 1 | package entity; 2 | 3 | public class HelloWorldA { 4 | HelloWorldB helloWorldB; 5 | String hello; 6 | public HelloWorldA(HelloWorldB helloWorldB,String hello,HelloWorldB helloWorldB1) { 7 | helloWorldB = this.helloWorldB; 8 | 9 | } 10 | 11 | public String getHello() { 12 | return hello; 13 | } 14 | 15 | public void setHello(String hello) { 16 | this.hello = hello; 17 | } 18 | 19 | public HelloWorldA(HelloWorldB helloWorldB) { 20 | } 21 | 22 | public HelloWorldA() { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/entity/HelloWorldB.java: -------------------------------------------------------------------------------- 1 | package entity; 2 | 3 | public class HelloWorldB { 4 | 5 | public HelloWorldB(HelloWorldA helloWorldA) { 6 | 7 | } 8 | public HelloWorldB() { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/entity/HelloWorldService.java: -------------------------------------------------------------------------------- 1 | package entity; 2 | 3 | public class HelloWorldService { 4 | private String text; 5 | public void helloWorld() { 6 | System.out.println(text + "hello World"); 7 | } 8 | 9 | public String getText() { 10 | return text; 11 | } 12 | 13 | public void setText(String text) { 14 | this.text = text; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/exception/BeanCurrentlyInCreationException.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | public class BeanCurrentlyInCreationException extends RuntimeException { 4 | public BeanCurrentlyInCreationException() { 5 | } 6 | 7 | public BeanCurrentlyInCreationException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/factory/AbstractBeanFactory.java: -------------------------------------------------------------------------------- 1 | package factory; 2 | 3 | import bean.BeanDefinition; 4 | import exception.BeanCurrentlyInCreationException; 5 | 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.util.Collections; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Set; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | public class AbstractBeanFactory implements BeanFactory { 14 | Map beanDefinitionMap; 15 | private Map beanMap = new HashMap<>(); 16 | private final Set singletonsCurrentlyInCreation = 17 | Collections.newSetFromMap(new ConcurrentHashMap<>(16)); 18 | 19 | 20 | public AbstractBeanFactory(){ 21 | beanDefinitionMap = new HashMap(); 22 | } 23 | public void registerBeanDefinition(String className, BeanDefinition beanDefinition) { 24 | beanDefinitionMap.put(className, beanDefinition); 25 | } 26 | public void cacheBean(String className, Object object) { 27 | beanMap.put(className, object); 28 | } 29 | 30 | public Object getBean(String beanName) { 31 | Object beanInstance = beanMap.get(beanName); 32 | if (beanInstance == null){ 33 | if (singletonsCurrentlyInCreation.contains(beanName)){ 34 | throw new BeanCurrentlyInCreationException(beanName); 35 | } 36 | singletonsCurrentlyInCreation.add(beanName); 37 | 38 | Object bean = null; 39 | try { 40 | bean = beanDefinitionMap.get(beanName).getBean(this); 41 | } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | ClassNotFoundException | InvocationTargetException e) { 42 | e.printStackTrace(); 43 | } 44 | 45 | singletonsCurrentlyInCreation.remove(beanName); 46 | return bean; 47 | } 48 | return beanInstance; 49 | } 50 | public String getBeanType(String beanId){ 51 | BeanDefinition beanDefinition = beanDefinitionMap.get(beanId); 52 | return beanDefinition.getBeanClassName(); 53 | } 54 | 55 | @Override 56 | public Object getObjectFromFactoryBean(FactoryBean factoryBean) { 57 | try { 58 | return factoryBean.getObject(); 59 | } catch (Exception e) { 60 | e.printStackTrace(); 61 | } 62 | return null; 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/factory/AutowireCapableBeanFactory.java: -------------------------------------------------------------------------------- 1 | package factory; 2 | 3 | public class AutowireCapableBeanFactory extends AbstractBeanFactory { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/factory/Aware.java: -------------------------------------------------------------------------------- 1 | package factory; 2 | 3 | public interface Aware { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/factory/BeanFactory.java: -------------------------------------------------------------------------------- 1 | package factory; 2 | 3 | import bean.BeanDefinition; 4 | 5 | public interface BeanFactory { 6 | public void registerBeanDefinition(String className, BeanDefinition beanDefinition) ; 7 | public void cacheBean(String className, Object object); 8 | 9 | public Object getBean(String beanName); 10 | public String getBeanType(String beanId) ; 11 | 12 | Object getObjectFromFactoryBean(FactoryBean object); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/factory/BeanFactoryAware.java: -------------------------------------------------------------------------------- 1 | package factory; 2 | public interface BeanFactoryAware extends Aware { 3 | 4 | void setBeanFactory(BeanFactory beanFactory) throws Exception; 5 | 6 | } -------------------------------------------------------------------------------- /src/main/java/factory/FactoryBean.java: -------------------------------------------------------------------------------- 1 | package factory; 2 | 3 | public interface FactoryBean { 4 | 5 | 6 | T getObject() throws Exception; 7 | 8 | Class getObjectType(); 9 | 10 | boolean isSingleton(); 11 | 12 | } -------------------------------------------------------------------------------- /src/main/java/factory/XMLBeanFactory.java: -------------------------------------------------------------------------------- 1 | package factory; 2 | 3 | import reader.XMLBeanDefinitionReader; 4 | import resource.ClassPathResource; 5 | 6 | import java.lang.reflect.InvocationTargetException; 7 | 8 | public class XMLBeanFactory extends AbstractBeanFactory { 9 | 10 | private XMLBeanDefinitionReader xmlBeanDefinitionReader = new XMLBeanDefinitionReader(this); 11 | public XMLBeanFactory(ClassPathResource classPathResource) { 12 | super(); 13 | xmlBeanDefinitionReader.registerBeanDefinition(classPathResource); 14 | } 15 | 16 | public void prepareInstanceBeans(){ 17 | beanDefinitionMap.forEach((beanName,beandefinition)-> { 18 | try { 19 | beandefinition.getBean(this); 20 | } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | ClassNotFoundException | InvocationTargetException e) { 21 | e.printStackTrace(); 22 | } 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/reader/XMLBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package reader; 2 | 3 | import bean.*; 4 | import factory.BeanFactory; 5 | import org.dom4j.Document; 6 | import org.dom4j.DocumentException; 7 | import org.dom4j.Element; 8 | import org.dom4j.io.SAXReader; 9 | import resource.ClassPathResource; 10 | 11 | import java.io.InputStream; 12 | import java.util.List; 13 | 14 | /** 15 | * 负责把通过xml读过来的资源封装成bean后注册到beanFactory 16 | */ 17 | public class XMLBeanDefinitionReader { 18 | private final BeanFactory beanFactory; 19 | private InputStream inputStream; 20 | 21 | private SAXReader reader = new SAXReader(); 22 | 23 | public XMLBeanDefinitionReader(BeanFactory beanFactory) { 24 | this.beanFactory = beanFactory; 25 | } 26 | 27 | public void registerBeanDefinition(ClassPathResource classPathResource) { 28 | inputStream = classPathResource.getInputStream(); 29 | try { 30 | doRegisterBeanDefinition(reader.read(inputStream)); 31 | } catch (DocumentException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | 36 | private void doRegisterBeanDefinition(Document document) { 37 | //获取根节点对象 38 | Element rootElement = document.getRootElement(); 39 | 40 | if (rootElement.getName().equals("beans")){ 41 | List elementList = rootElement.elements("bean"); 42 | 43 | if(elementList != null ){ 44 | elementList.forEach(this::parseBean); 45 | } 46 | 47 | } 48 | } 49 | 50 | private void parseBean(Element element) { 51 | String beanId = element.attributeValue("id"); 52 | String beanClass = element.attributeValue("class"); 53 | BeanDefinition beanDefinition = new BeanDefinition(); 54 | beanDefinition.setBeanClassName(beanClass); 55 | beanDefinition.setBeanId(beanId); 56 | 57 | 58 | List elements = element.elements(); 59 | PropertyValues propertyValues = new PropertyValues(); 60 | ConstructorValues constructorValues = new ConstructorValues(); 61 | 62 | elements.forEach(subElement ->{ 63 | String subElementName = subElement.getName(); 64 | if (subElementName.equals("property")){ 65 | propertyValues.addPropertyValue(parsePropertyElement(subElement)); 66 | 67 | } 68 | if (subElementName.equals("constructor-arg")){ 69 | constructorValues.addConstructorValue(parseConstructorArgElement(subElement)); 70 | } 71 | }); 72 | 73 | beanDefinition.setPropertyValues(propertyValues); 74 | beanDefinition.setConstructorValues(constructorValues); 75 | beanFactory.registerBeanDefinition(beanId,beanDefinition); 76 | } 77 | 78 | private ConstructorValue parseConstructorArgElement(Element subElement) { 79 | String index = subElement.attributeValue("index"); 80 | String ref = subElement.attributeValue("ref"); 81 | String value = subElement.attributeValue("value"); 82 | String name = subElement.attributeValue("name"); 83 | 84 | return new ConstructorValue(index,ref,value,name); 85 | } 86 | 87 | private PropertyValue parsePropertyElement(Element subElement) { 88 | String name = subElement.attributeValue("name"); 89 | String value = subElement.attributeValue("value"); 90 | String ref = subElement.attributeValue("ref"); 91 | return new PropertyValue(name, value,ref); 92 | } 93 | 94 | public BeanFactory getBeanFactory() { 95 | return beanFactory; 96 | } 97 | 98 | public InputStream getInputStream() { 99 | return inputStream; 100 | } 101 | 102 | public void setInputStream(InputStream inputStream) { 103 | this.inputStream = inputStream; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/resource/ClassPathResource.java: -------------------------------------------------------------------------------- 1 | package resource; 2 | 3 | import java.io.InputStream; 4 | 5 | /** 6 | * 此类通过类路径获取文件的 inputStream 7 | */ 8 | public class ClassPathResource { 9 | private InputStream inputStream; 10 | public ClassPathResource(String fileName) { 11 | inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName); 12 | } 13 | 14 | public InputStream getInputStream() { 15 | return inputStream; 16 | } 17 | 18 | public void setInputStream(InputStream inputStream) { 19 | this.inputStream = inputStream; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/beanFactoryTest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/test/java/SpringAopTest.java: -------------------------------------------------------------------------------- 1 | import aop.ProxyFactory; 2 | import aopAdvice.PerformerAfterAdvice; 3 | import aopAdvice.PerformerBeforeAdvice; 4 | import aopEntity.Apology; 5 | import aopEntity.Performer; 6 | import aopEntity.Singer; 7 | import context.ApplicationContext; 8 | import context.ClassPathXmlApplicationContext; 9 | import org.junit.Test; 10 | 11 | public class SpringAopTest { 12 | /** 13 | * 测试aspectj 14 | */ 15 | @Test 16 | public void test2() { 17 | ApplicationContext ctx = 18 | new ClassPathXmlApplicationContext("spring-idol.xml"); 19 | 20 | Performer performer = (Performer) ctx.getBean("bo"); 21 | performer.perform(); 22 | System.out.println("-----------------------------"); 23 | Performer performer2 = (Performer) ctx.getBean("william"); 24 | performer2.perform(); 25 | } 26 | 27 | /** 28 | * 测试简单的jdk代理和cglib代理 29 | */ 30 | @org.junit.Test 31 | public void test() { 32 | ProxyFactory proxyFactory = new ProxyFactory(); // 创建代理工厂 33 | proxyFactory.setTarget(new Singer("aaa","bbb")); // 射入目标类对象 34 | proxyFactory.addAdvice(new PerformerBeforeAdvice()); // 添加前置增强 35 | proxyFactory.addAdvice(new PerformerAfterAdvice()); // 添加后置增强 36 | 37 | Performer singer = (Performer) proxyFactory.getProxy(); // 从代理工厂中获取代理 38 | singer.perform(); 39 | } 40 | 41 | /** 42 | * 测试ProxyFactoryBean 43 | */ 44 | @org.junit.Test 45 | public void test3() { 46 | ApplicationContext ctx = 47 | new ClassPathXmlApplicationContext("ProxyFactoryBean.xml"); 48 | 49 | Performer performer = (Performer) ctx.getBean("proxyFactoryBean"); 50 | 51 | performer.perform(); 52 | } 53 | /** 54 | * 测试DelegatingIntroductionInterceptor 55 | */ 56 | @org.junit.Test 57 | public void test4() { 58 | ApplicationContext context = new ClassPathXmlApplicationContext("DelegatingIntroductionInterceptor.xml"); 59 | Singer performer = (Singer) context.getBean("proxyFactoryBean"); 60 | performer.perform(); 61 | Apology apology = (Apology) context.getBean("proxyFactoryBean"); 62 | apology.saySorry("haha"); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/SpringApplicationContextTest.java: -------------------------------------------------------------------------------- 1 | import context.ApplicationContext; 2 | import context.ClassPathXmlApplicationContext; 3 | import entity.HelloWorldA; 4 | 5 | public class SpringApplicationContextTest { 6 | 7 | /** 8 | * 通过读取xml文件来进行bean的读取 9 | */ 10 | @org.junit.Test 11 | public void test3() throws Exception { 12 | // 1.初始化beanfactory 13 | 14 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beanFactoryTest.xml"); 15 | 16 | // 5.获取bean 17 | HelloWorldA helloWorldService = (HelloWorldA) applicationContext.getBean("helloWorldA"); 18 | System.out.println(helloWorldService); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/SpringTest.java: -------------------------------------------------------------------------------- 1 | import entity.HelloWorldA; 2 | import factory.BeanFactory; 3 | import factory.XMLBeanFactory; 4 | import resource.ClassPathResource; 5 | 6 | public class SpringTest { 7 | 8 | /** 9 | * 通过读取xml文件来进行bean的读取 10 | */ 11 | @org.junit.Test 12 | public void test3() throws Exception { 13 | // 1.初始化beanfactory 14 | BeanFactory beanFactory = new XMLBeanFactory(new ClassPathResource("beanFactoryTest.xml")); 15 | 16 | // 5.获取bean 17 | HelloWorldA helloWorldService = (HelloWorldA) beanFactory.getBean("helloWorldA"); 18 | System.out.println(helloWorldService); 19 | } 20 | 21 | // @org.junit.Test 22 | // public void test4() throws Exception { 23 | // Class clazz = HelloWorldA.class; 24 | // Constructor constructor = clazz.getConstructor(new Class[]{HelloWorldB.class}); 25 | // HelloWorldA helloWorldA = (HelloWorldA)constructor.newInstance(new HelloWorldB()); 26 | // 27 | // System.out.println(helloWorldA); 28 | // 29 | // } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/aopAdvice/PerformerAfterAdvice.java: -------------------------------------------------------------------------------- 1 | package aopAdvice; 2 | 3 | import aop.AfterReturningAdvice; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | public class PerformerAfterAdvice implements AfterReturningAdvice { 8 | @Override 9 | public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { 10 | System.out.println("THAT WAS GREAT"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/aopAdvice/PerformerAroundAdvice.java: -------------------------------------------------------------------------------- 1 | package aopAdvice; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | public class PerformerAroundAdvice implements MethodInterceptor { 9 | @Override 10 | public Object invoke(MethodInvocation methodInvocation) throws Throwable { 11 | Method method = methodInvocation.getMethod(); 12 | start(method); 13 | methodInvocation.proceed(); 14 | end(method); 15 | return null; 16 | } 17 | 18 | private void start(Method method) { 19 | System.out.println(method.getName()+" 开始运行"); 20 | } 21 | 22 | private void end(Method method) { 23 | System.out.println(method.getName()+" 结束运行"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/aopAdvice/PerformerBeforeAdvice.java: -------------------------------------------------------------------------------- 1 | package aopAdvice; 2 | 3 | import aop.MethodBeforeAdvice; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | public class PerformerBeforeAdvice implements MethodBeforeAdvice { 8 | @Override 9 | public void before(Method method, Object[] args, Object target) throws Throwable { 10 | System.out.println("GREETING PERFORMER"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/aopEntity/Apology.java: -------------------------------------------------------------------------------- 1 | package aopEntity; 2 | 3 | public interface Apology { 4 | 5 | void saySorry(String name); 6 | } -------------------------------------------------------------------------------- /src/test/java/aopEntity/GreetingIntroAdvice.java: -------------------------------------------------------------------------------- 1 | package aopEntity; 2 | 3 | import aop.DelegatingIntroductionInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | 6 | public class GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology { 7 | 8 | @Override 9 | public void saySorry(String name) { 10 | System.out.println("Sorry! " + name); 11 | } 12 | 13 | @Override 14 | public Object invoke(MethodInvocation invocation) throws Throwable { 15 | return super.invoke(invocation); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/aopEntity/NiceJudge.java: -------------------------------------------------------------------------------- 1 | package aopEntity; 2 | 3 | public class NiceJudge { 4 | public NiceJudge() {} 5 | 6 | public void greetPerformer() { 7 | System.out.println("GREETING PERFORMER"); 8 | } 9 | 10 | public void saySomethingNice() { 11 | System.out.println("THAT WAS GREAT"); 12 | } 13 | 14 | public void saySomethingNiceAnyway() { 15 | System.out.println("IT WASN'T GREAT, BUT I LOVE YOU ANYWAY"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/aopEntity/Performer.java: -------------------------------------------------------------------------------- 1 | package aopEntity; 2 | 3 | public interface Performer { 4 | void perform(); 5 | } 6 | -------------------------------------------------------------------------------- /src/test/java/aopEntity/Singer.java: -------------------------------------------------------------------------------- 1 | package aopEntity; 2 | 3 | import exception.PerformanceException; 4 | 5 | public class Singer implements Performer{ 6 | private String name; 7 | private String song; 8 | 9 | public Singer(String name) { 10 | this(name, null); 11 | } 12 | public Singer() { 13 | this("default", "default"); 14 | } 15 | 16 | public Singer(String name, String song) { 17 | this.name = name; 18 | this.song = song; 19 | } 20 | 21 | public void perform() throws PerformanceException { 22 | if(song == null) { 23 | throw new PerformanceException(name + " doesn't have a song to sing."); 24 | } 25 | System.out.println(name + " is singing " + song); 26 | } 27 | 28 | public void setSong(String song) { 29 | this.song = song; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/exception/PerformanceException.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | public class PerformanceException extends RuntimeException { 4 | public PerformanceException(String s) { 5 | super(s); 6 | } 7 | 8 | public PerformanceException() { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/DelegatingIntroductionInterceptor.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/resources/ProxyFactoryBean.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/test/resources/spring-idol.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 13 | 14 | 15 | 16 | 19 | 22 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | --------------------------------------------------------------------------------