在前面的文章中我们讲述了Spring的基本概念和及IOC和AOP在这篇文章中我们来模拟实现Spring的IOC操作
(1)关于模拟实现IOC我们主要实现两个功能
@Test
public void testService(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
UserService userservice = context.getBean("userService", UserService.class);
userservice.add();
}
@Component(singleton = false)
public class ClassOne {
@Autowired
private Complex complex;
@Autowired
private Point point;
}
(2)实现原理
@Retention(RUNTIME)
@Target(TYPE)
public @interface Component {
boolean singleton() default true;//默认储存单例对象
}
Autowired注解
@Retention(RUNTIME)
@Target({ FIELD, METHOD })
public @interface Autowired {
}
(3)代码实现
public class BeanDefinition {
private Class<?> klass;
private Object object;
private boolean singleton;
private boolean inject;
BeanDefinition() {
this.inject = false;
this.singleton = true;
}
boolean isSingleton() {
return singleton;
}
void setSingleton(boolean singleton) {
this.singleton = singleton;
}
boolean isInject() {
return inject;
}
void setInject(boolean inject) {
this.inject = inject;
}
Class<?> getKlass() {
return klass;
}
void setKlass(Class<?> klass) {
this.klass = klass;
}
Object getObject() {
return object;
}
void setObject(Object object) {
this.object = object;
}
}
public class BeanFactory {
//容器
private static final Map<String, BeanDefinition> beanPool;
static {
beanPool = new HashMap<String, BeanDefinition>();
}
public BeanFactory() {
}
//包扫描
public void scanBeanByPackage(String packageName) {
new PackageScanner() {
@Override
//得到带有Component的类
public void dealClass(Class<?> klass) {
if (klass.isPrimitive()
|| klass.isInterface()
|| klass.isAnnotation()
|| klass.isEnum()
|| klass.isArray()
|| !klass.isAnnotationPresent(Component.class)) {
return;
}
try {
//生成类对象,并放入容器中
Object object = null;
Component component = klass.getAnnotation(Component.class);
boolean singleton = component.singleton();
BeanDefinition beanDefinition = new BeanDefinition();
if (singleton) {
object = klass.newInstance();
}
beanDefinition.setSingleton(singleton);
beanDefinition.setKlass(klass);
beanDefinition.setObject(object);
beanPool.put(klass.getName(), beanDefinition);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}.scanPackage(packageName);
}
BeanDefinition getBeanDefinition(String klassName) {
return beanPool.get(klassName);
}
BeanDefinition getBeanDefinition(Class<?> klass) {
return getBeanDefinition(klass.getName());
}
private void injectProperties(BeanDefinition beanDefinition) throws RuntimeException {
Class<?> klass = beanDefinition.getKlass();
Object object = beanDefinition.getObject();
Field[] fields = klass.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(Autowired.class)) {
continue;
}
// 应该先对inject进行判断,若为true,表示该对象已经完成注入;
// 这种方法可以避免循环依赖。
field.setAccessible(true);
Object value = getBean(field.getType());
if (value == null) {
throw new HasNoBeanException("类[" + klass.getName()
+ "]的[" + field.getName()
+ "]成员没有对应的Bean!");
}
try {
field.set(object, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private static BeanDefinition getBeanObject(String className) {
BeanDefinition bean = beanPool.get(className);
if (bean == null) {
return null;
}
Object object = null;
if (!bean.isSingleton()) {
Class<?> klass = bean.getKlass();
try {
object = klass.newInstance();
bean.setObject(object);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return bean;
}
@SuppressWarnings("unchecked")
public <T> T getBean(String klassName) throws RuntimeException {
BeanDefinition bean = getBeanObject(klassName);
if (bean == null) {
System.out.println("Bean[" + klassName + "]不存在!");
return null;
}
Object object = bean.getObject();
if (!bean.isInject() || !bean.isSingleton()) {
bean.setInject(true);
// 这里完成对object中需要注入的成员的初始化工作!
injectProperties(bean);
}
return (T) object;
}
public <T> T getBean(Class<?> klass) throws RuntimeException {
return getBean(klass.getName());
}
}
(4)测试
@Component
public class ClassOne {
public ClassOne() {
System.out.println("ClassOne...");
}
}
public class Demo {
public static void main(String[] args) {
BeanFactory beanFactory = new BeanFactory();
beanFactory.scanBeanByPackage("some_class");
ClassOne classOne = beanFactory.getBean(ClassOne.class);
}
}
@Component(singleton = false)
public class ClassOne {
public ClassOne() {
System.out.println("ClassOne...");
}
}
public class Demo {
public static void main(String[] args) {
BeanFactory beanFactory = new BeanFactory();
beanFactory.scanBeanByPackage("some_class");
ClassOne classOne = beanFactory.getBean(ClassOne.class);
System.out.println("classOne-->" + classOne + "classOne.hashCode()-->" + classOne.hashCode());
ClassOne classOne2 = beanFactory.getBean(ClassOne.class);
System.out.println("classOne2-->" + classOne2 + "classOne2.hashCode-->" + classOne2.hashCode());
}
}
@Component
public class ClassTwo {
public ClassTwo() {
System.out.println("ClassTwo...");
}
@Autowired
public ClassOne classone;
}
public class Demo {
public static void main(String[] args) {
BeanFactory beanFactory = new BeanFactory();
beanFactory.scanBeanByPackage("some_class");
ClassTwo classtwo = beanFactory.getBean(ClassTwo.class);
}
}
@Component
public class ClassTwo {
public ClassTwo() {
System.out.println("ClassTwo...");
}
@Autowired
public ClassOne classone;
}
@Component(singleton = false)
public class ClassOne {
public ClassOne() {
System.out.println("ClassOne...");
}
@Autowired
public ClassTwo classtwo;
}
public class Demo {
public static void main(String[] args) {
BeanFactory beanFactory = new BeanFactory();
beanFactory.scanBeanByPackage("some_class");
ClassTwo classtwo = beanFactory.getBean(ClassTwo.class);
}
}