工具类作用:
1.根据配置文件反射创建类对象存入容器,
2.根据对象里的自动装配注解,定义成员对象
一:配置文件配置类的全限定名
配置好的类会用工具类存储到map容器中
<beans>
<bean id="UserService" className="com.alibaba.service.impl.UserServiceImpl"></bean>
<bean id="UserDao" className="com.alibaba.dao.UserDaoImpl.UserDaoImpl"></bean>
</beans>
二:自定义工厂工具类
1.解析xml配置文件
2.为配置文件配置的类创建对象存入map
3.根据注解为容器里的对象的成员对象赋值(初始化)
4.根据参数返回对象的方法
package com.alibaba.utils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Author:ZZZ
* @Date: 2020/12/24 15:51
* @Version 1.0
*/
public class Factory {
//容器Map
static Map <String, Object> containerMap = new HashMap();
static {
//读取bean的xml配置文件
InputStream is = Factory.class.getClassLoader().getResourceAsStream("Simulate_Spring.xml");
SAXReader saxReader = new SAXReader();
try {
//dom4j将整个配置文件成Document对象
Document document = saxReader.read(is);
// List<Element> list = document.selectNodes("//bean");
//Document读取根节点
Element rootElement = document.getRootElement();
//通过根节点拿到所有的配置文件的子节点 <bean id="" class="" />
List <Element> elements = rootElement.elements();
//将配置的所有内容都实例化对象
for (Element element : elements) {
//对象名字
String id = element.attributeValue("id");
//类的全限定名
String className = element.attributeValue("className");
System.out.println(id+":"+className);
//类Class对象
Class<?> aClass = Class.forName(className);
//反射创建对象
Object obj = aClass.newInstance();
//存入容器
containerMap.put(id,obj);
}
//遍历容器将带有autowired的注解的成员初始化
for (Map.Entry<String, Object> entry : containerMap.entrySet()) {
// 对象
Object objectClass = entry.getValue();
// 对象的成员变量
Field[] declaredFields = objectClass.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
// 对象的每个成员变量
// 成员变量上的注解
for (Annotation declaredAnnotation : declaredField.getDeclaredAnnotations()) {
// 注解上有自动装配
if (declaredAnnotation.toString().equals("@com.alibaba.annotation.MyAutoWired()")) {
// 将当前成员变量第一个字母大写
char[] chars = declaredField.getName().toCharArray();
chars[0]-=32;
String strDeclaredField = new String(chars);
declaredField.set(objectClass,getObject(strDeclaredField));
}
}
}
}
}
catch (Exception e){
e.printStackTrace();
}
}
//工厂获取对象
public static Object getObject(String id) {
try {
Object obj = containerMap.get(id);
if (obj != null) {
//容器中有该对象
return obj;
} else {
throw new RuntimeException("容器找不到该对象");
}
} catch (Exception e) {
return null;
}
}
}
自定义注解
作用:为了工具类实现自动装配
package com.alibaba.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author:ZZZ
* @Date: 2021/1/4 15:41
* @Version 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface MyAutoWired {
}
UserServiceImpl:
该类的方法调用了UserDao的方法,用自定义注解实现自动装配成员userDao
接口略
package com.alibaba.service.impl;
import com.alibaba.User;
import com.alibaba.annotation.MyAutoWired;
import com.alibaba.dao.UserDao;
import com.alibaba.service.UserService;
import com.alibaba.utils.Factory;
/**
* @Author:ZZZ
* @Date: 2020/12/24 15:42
* @Version 1.0
*/
public class UserServiceImpl implements UserService {
@MyAutoWired
public UserDao userDao ;
@Override
public User findById(int id) {
return userDao.findById(id);
}
}
UserDaoImpl
接口略
package com.alibaba.dao.UserDaoImpl;
import com.alibaba.User;
import com.alibaba.dao.UserDao;
/**
* @Author:ZZZ
* @Date: 2020/12/24 15:44
* @Version 1.0
*/
public class UserDaoImpl implements UserDao {
@Override
public User findById(int id) {
System.out.println("查询User");
return new User();
}
}
测试类
从容器里拿UserServiceImpl,UserServiceImpl.findById()方法调用的是UserDao的方法,反射可不会为对象成员的初始化,但是工具类里定义了成员,所以不会空指针异常
@Test
public void test_hello() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
UserService userService = (UserService) Factory.getObject("UserService");
System.out.println(userService);
userService.findById(1);
}
另外知识:
1.反射时注解需要存活到运行期间:@Retention(RetentionPolicy.RUNTIME)
2.char字符串转String方法
String str=new String (char[]c);
3.String转char方法
char []c=c.toCharArray();
4.反射给类的成员对象(Field)初始化
UserService userService= (UserService) Factory.getObject("UserService");
Class<?> clazz = Class.forName("com.alibaba.service.impl.UserServiceImpl");
Field field = clazz.getField("userDao");
field.set(userService,Factory.getObject("UserDao"));
5.遍历map的方法
for (Map.Entry<String, Object> entry : containerMap.entrySet()) {
entry.getKey();
entry.getValue();
}
6.静态代码块最先执行,静态代码块能调用静态方法。