文章目录
- 1.目录
- 2.SmartAnimal.java 接口(JDK代理必须有接口)
- 3.SmartDog.java
- 4.SmartAnimalAspect.java
- 5.SunSpringApplicationContext.java
- 1.在Bean的后置处理器之后使用动态代理
- 2.完整代码
- 6.测试
- 1.AppMain.java 调用被代理的类的方法
- 2.结果
- 7.Spring底层机制总结
- 1.扫描包,存储Bean定义信息,初始化单例池,依赖注入
- 2.后置处理器的Before方法对Bean进行处理
- 3.实现InitializingBean接口或者有@PostConstruct注解的初始化方法被调用
- 4.后置处理器的After方法对Bean进行处理
- 5.如果发现某个类被AOP了,则在后置处理器之后就会返回代理对象,当目标对象使用代理对象调用方法时,就可以得到目标对象和调用的方法的信息
1.目录

2.SmartAnimal.java 接口(JDK代理必须有接口)
package com.sunxiansheng.sunspring.compent;
public interface SmartAnimal {public float getSum(float a, float b);public float getSub(float a, float b);}
3.SmartDog.java
package com.sunxiansheng.sunspring.compent;import com.sunxiansheng.sunspring.annotation.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component
public class SmartDog implements SmartAnimal {private static final Logger log = LoggerFactory.getLogger(SmartDog.class);@Overridepublic float getSum(float a, float b) {log.info("SmartDog...getSum...res=" + (a + b));return a + b;}@Overridepublic float getSub(float a, float b) {log.info("SmartDog...getSub...res=" + (a - b));return a - b;}}
4.SmartAnimalAspect.java
package com.sunxiansheng.sunspring.compent;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SmartAnimalAspect {private static final Logger log = LoggerFactory.getLogger(SmartAnimalAspect.class);public static void showBeginLog() {log.info("AOP:前置通知-方法执行开始");}public static void showEndLog() {log.info("AOP:后置通知-方法执行结束");}}
5.SunSpringApplicationContext.java
1.在Bean的后置处理器之后使用动态代理

2.完整代码
package com.sunxiansheng.sunspring.ioc;import com.sunxiansheng.sunspring.annotation.*;
import com.sunxiansheng.sunspring.annotation.myenum.MyScope;
import com.sunxiansheng.sunspring.compent.SmartAnimalAspect;
import com.sunxiansheng.sunspring.processor.BeanPostProcessor;
import com.sunxiansheng.sunspring.processor.InitializingBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public class SunSpringApplicationContext {private static final Logger log = LoggerFactory.getLogger(SunSpringApplicationContext.class);private ConcurrentHashMap<String, BeanDefintion> beanDefintionMap = new ConcurrentHashMap<>();private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();public SunSpringApplicationContext(Class<?> configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {beanDefinitionByScan(configClass);initSingletonObjects();}private void populateBeans(Object bean) {Class<?> clazz = bean.getClass();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(Resource.class)) {String fieldName = field.getName();Object beanObject = null;BeanDefintion beanDefintion = beanDefintionMap.get(fieldName);try {beanObject = getBean(fieldName);} catch (Exception e) {throw new RuntimeException(e);}field.setAccessible(true);try {field.set(bean, beanObject);log.info("依赖注入成功:{} => {}.{}", beanObject.getClass(), clazz, fieldName);} catch (IllegalAccessException e) {e.printStackTrace();}}}}private void initSingletonObjects() {beanDefintionMap.forEach((beanName, beanDefintion) -> {try {Object bean = createBean(beanDefintion);if (bean != null) {singletonObjects.put(beanName, bean);}} catch (Exception e) {e.printStackTrace();}});log.info("根据bean定义信息初始化单例池:{}", singletonObjects);}public Object getBean(String name) throws Exception {BeanDefintion beanDefintion = beanDefintionMap.get(name);if (beanDefintion == null) {throw new NullPointerException("在bean定义中没有找到bean对象");}MyScope scope = beanDefintion.getScope();Object bean = null;if (scope == MyScope.SINGLETON) {bean = singletonObjects.get(name);} else {bean = createProtoTypeBean(beanDefintion);}populateBeans(bean);Object current = bean;for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {Object bean1 = beanPostProcessor.postProcessBeforeInitialization(bean, name);if (bean1 != null) {current = bean1;}}init(current);for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {bean = beanPostProcessor.postProcessAfterInitialization(current, name);if (bean == null) {bean = current;}}if (name.equals("smartDog")) {final Object proxyObject = current;bean = Proxy.newProxyInstance(current.getClass().getClassLoader(), current.getClass().getInterfaces(), (proxy, method, args) -> {SmartAnimalAspect.showBeginLog();Object invoke = method.invoke(proxyObject, args);SmartAnimalAspect.showEndLog();return invoke;});log.info("SmartDog返回代理对象:{}", bean.getClass());return bean;}log.info("getBean:{}", bean.getClass());return bean;}public void init(Object bean) {if (bean instanceof InitializingBean) {((InitializingBean) bean).afterPropertiesSet();}}private Object createBean(BeanDefintion beanDefintion) throws Exception {Class<?> clazz = beanDefintion.getClazz();if (beanDefintion.getScope() == MyScope.PROTOTYPE) {return null;}Object bean = clazz.getDeclaredConstructor().newInstance();return bean;}private static Object createProtoTypeBean(BeanDefintion beanDefintion) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {Class<?> clazz = beanDefintion.getClazz();Object bean = clazz.getDeclaredConstructor().newInstance();return bean;}private void beanDefinitionByScan(Class<?> configClass) {ComponentScan componentScan = configClass.getDeclaredAnnotation(ComponentScan.class);String path = componentScan.packagePath();log.info("扫描的包路径:{}", path);ClassLoader classLoader = SunSpringApplicationContext.class.getClassLoader();path = path.replace(".", "/");URL resource = classLoader.getResource(path);File file = new File(resource.getFile());if (file.isDirectory()) {File[] files = file.listFiles();for (File f : files) {String absolutePath = f.getAbsolutePath();if (absolutePath.endsWith(".class")) {String className = extractClassName(absolutePath);String fullPath = path.replace("/", ".") + "." + className;Class<?> aClass = null;try {aClass = classLoader.loadClass(fullPath);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}if (aClass.isAnnotationPresent(Component.class)) {log.info("扫描到Spring Bean:{}", aClass);if (BeanPostProcessor.class.isAssignableFrom(aClass)) {Object o = null;try {o = aClass.getDeclaredConstructor().newInstance();} catch (Exception e) {log.info("BeanPostProcessor实例化失败:{}", e);}if (o instanceof BeanPostProcessor) {beanPostProcessorList.add((BeanPostProcessor) o);}log.info("BeanPostProcessor实例化成功:{}", o);continue;}BeanDefintion beanDefintion = new BeanDefintion();if (aClass.isAnnotationPresent(Scope.class)) {Scope scope = aClass.getDeclaredAnnotation(Scope.class);MyScope value = scope.value();beanDefintion.setScope(value);} else {beanDefintion.setScope(MyScope.SINGLETON);}beanDefintion.setClazz(aClass);Component component = aClass.getDeclaredAnnotation(Component.class);String beanName = component.value();if ("".equals(beanName)) {beanName = className.substring(0, 1).toLowerCase() + className.substring(1);}beanDefintionMap.put(beanName, beanDefintion);} else {log.info("这不是一个Spring Bean={}", aClass);}}}}log.info("将bean定义信息放到beanDefintionMap:{}", beanDefintionMap);}private String extractClassName(String filePath) {int lastSlashIndex = filePath.lastIndexOf('/');int lastDotIndex = filePath.lastIndexOf('.');return filePath.substring(lastSlashIndex + 1, lastDotIndex);}}
6.测试
1.AppMain.java 调用被代理的类的方法

2.结果

7.Spring底层机制总结
1.扫描包,存储Bean定义信息,初始化单例池,依赖注入
2.后置处理器的Before方法对Bean进行处理
3.实现InitializingBean接口或者有@PostConstruct注解的初始化方法被调用
4.后置处理器的After方法对Bean进行处理
5.如果发现某个类被AOP了,则在后置处理器之后就会返回代理对象,当目标对象使用代理对象调用方法时,就可以得到目标对象和调用的方法的信息