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);
@Override
public float getSum(float a, float b) {
log.info("SmartDog...getSum...res=" + (a + b));
return a + b;
}
@Override
public 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了,则在后置处理器之后就会返回代理对象,当目标对象使用代理对象调用方法时,就可以得到目标对象和调用的方法的信息