一.设计流程
第一步:User书写数据类型
这里是书写数据库的基本数据结构
第二步:
1.@Controller
这里是对操作类的注解,用于区分类文件,便于反射的时候创建对象
2.@Service
这里是对业务类的注解,用于区分类文件,便于反射的时候创建对象
3.@Repository
这里是多Dao层的注解,用于区分类文件,便于反射的时候穿件对象
4.@Autowired
这里是多私有属性的注解,便于依赖注入,实现各对象之间的关联
第三步:UserDao层
这里是书写数据库操作层
第四步:UserService这是业务层
这里是业务层
第五步:UserController这是表现层
这里是表现层,具体操作的功能实现的类,调用业务层执行业务逻辑(查询)
第六步:container
这里是容器,主要是用于具体的操作的对象做相关操作时,不需要创建对象,所有的对象都装在该容器里.
这里容器层有很多操作.
第一个方法:给容器Map赋值.
1.获取当前类下的所有的class文件
2.将class文件转成类的全局限定名字,也就是类在包下的路径名
3.创建一个成员变量Map作为容器
4.通过反射,和注解筛选,创建map中的value值.
5.把类的包下路径名转为首字母小写的类名作为key值.
6.将key值和value值放入容器Map中.
第二个方法:给容器依赖注入
8.遍历容器,获得所有的value值
9.通过反射,注解筛选出带@Autowired的字段.
10.通过方法三给该字段赋值.
第三个方法:获取容器Map中的value值,也就是对象
11.public T getValue(String beanName) {
return (T)BeansFactory.beans.get(beanName);
}
第七步:TestUser
这是具体的操作的每个对象,也就是每个客户.
1.获取当前类的路径.
2.创建BeansFactory对象.
3.给对象中Map字段赋值
4.依赖注入
5.通过key获取容器Map中的对象.
6.调用对象的方法
第一步,写pojo对象
public class User {
private Integer id;
private String name;
private String company;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", company=" + company + "]";
}
}
第二步
书写注解@controller,@Service,@Repostory,@Autowired.
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Repository {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}
第三-第五步
书写controller层/service层/dao层
@Controller
public class UserController {
//这是依赖属性,稍后建立容器需要依赖注入的字段,所以需要加上注解
@Autowired
private UserService userService;
//输入参数id,获取一个数据User
public User seletOne(Integer id) {
return userService.seletOne(id);
}
//获取全部的数据User
public List<User> seletList(){
return userService.seletList();
}
}
@Service
public class UserService {
//这是依赖属性,稍后建立容器需要依赖注入的字段,所以需要加上注解
@Autowired
private UserDao userDao;
//输入参数id,获取一个数据User
public User seletOne(Integer id) {
return userDao.seletOne(id);
}
//获取全部的数据User
public List<User> seletList(){
return userDao.seletList();
}
}
@Repository
public class UserDao {
//输入参数id,返回一条数据
public User seletOne(Integer id) {
//这下面的代码,后面是直接调用数据库的数据
//这里是模拟返回的数据
User u = new User();
u.setId(id);
u.setName("马云");
u.setCompany("阿里巴巴");
return u;
}
//返回全部的数据
public List<User> seletList(){
List<User> userList = new ArrayList<User>();
User u1 = new User();
u1.setId(0002);
u1.setName("马化腾");
u1.setCompany("腾讯");
userList.add(u1);
User u2 = new User();
u2.setId(0002);
u2.setName("李彦宏");
u2.setCompany("百度");
userList.add(u2);
User u3 = new User();
u3.setId(0002);
u3.setName("王兴");
u3.setCompany("美团");
userList.add(u3);
//返回集合
return userList;
}
}
第六步
书写框架,生成容器container
这里是容器,主要是用于具体的操作的对象做相关操作时,不需要创建对象,所有的对象都装在该容器里.
这里容器层有很多操作. 第一个方法:给容器Map赋值.
1.获取当前类下的所有的class文件
2.将class文件转成类的全局限定名字,也就是类在包下的路径名
3.创建一个成员变量Map作为容器
4.通过反射,和注解筛选,创建map中的value值.
5.把类的包下路径名转为首字母小写的类名作为key值.
6.将key值和value值放入容器Map中. 第二个方法:给容器依赖注入
8.遍历容器,获得所有的value值
9.通过反射,注解筛选出带@Autowired的字段.
10.通过方法三给该字段赋值. 第三个方法:获取容器Map中的value值,也就是对象
11.public T getValue(String beanName) { return (T)BeansFactory.beans.get(beanName); }
容器初始化类
public class ComponentScan {
//初始化一个容器
private static final Map<String,Object> beans = new HashMap<String,Object>();
/**
* 这里是给容器赋值.
* @param pathName 通过路径,给容器赋值
* @throws Exception
*/
public void setBeans(String pathName) throws Exception {
//获取该路劲下的class文件
List<String> pathNameList = BeansUtil.scanFile(pathName);
//截取字符串成类的包名路径
for(String s : pathNameList) {
//调用工具类方法,获取类的包名路劲
String className = BeansUtil.parse(s);
//调用工具类,筛选出具有相关注解的类
Class<?> clazz = Class.forName(className);
Repository re = clazz.getDeclaredAnnotation(Repository.class);
Service se = clazz.getDeclaredAnnotation(Service.class);
Controller co = clazz.getDeclaredAnnotation(Controller.class);
if(re != null || se != null || co != null) {
Object obj = clazz.newInstance();
//这里调用方法,重新设置key的值,因为key的值简单的话,后面调用会更简易.
String beanName = BeansUtil.parseBeanName(className);
beans.put(beanName, obj);
}
}
}
/**
* 这是依赖注入,必须的重新写一个方法,因为如果卸载容器初始化里
* 则,因为容器赋值的先后顺序不同,会导致有些依赖注入的对象不能注入
* @throws Exception
*/
public void inject() throws Exception {
//遍历容器
for(String s : beans.keySet()) {
//获取容器中的对象
Object obj = beans.get(s);
//利用反射的原理,获取字段上的注解
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields) {
//设置字段的可见性
f.setAccessible(true);
//获取字段上的@Autowired注解
Autowired aut = f.getDeclaredAnnotation(Autowired.class);
//如果该注解不为空,则调用下面的方法,给成员变量也就是属性,注入对象.
if(aut != null) {
//这里就和前面的为什么key值得首字母要小写对应起来了
//因为这里获得的字段的名字是类名首字母小写的,所以可以直接传入到
//getValue方法内,直接获取对象值
f.set(obj, getValue(f.getName()));
}
}
}
}
/**
* 通过beans的key值来调用具体的对象,也就是Ioc核心的控制反转
* 具体的操作只能通过容器的key值来获取容器中的对象
* 这里注意要用泛型,因为将来的从容器中获取的对象则不需要再强转一次了
*/
public <T> T getValue(String beanName) {
return (T)ComponentScan.beans.get(beanName);
}
}
工具类
public class BeansUtil {
//设置一个集合用于接收返回的class文件集合
private static final List<String> list = new ArrayList<String>();
/**
* @param pathName 这是你想查找的路径参数
* @return scanFile 返回List<string>,这个集合是该路径下的所有的class文件
*/
public static List<String> scanFile(String pathName){
File file = new File(pathName);
File[] fileArray = file.listFiles();
for(File f : fileArray) {
String className = f.getAbsolutePath();
if(f.isDirectory()) {
pathName = className;
scanFile(pathName);
}else {
if(className.endsWith(".class")){
list.add(f.getAbsolutePath());
}
}
}
return list;
}
/**
* 这是将一个绝对路径类名转换成包路径类名
* @param pathName 绝对路径路径
* @return 包名路径
*/
public static String parse(String pathName){
String newName = pathName.substring(pathName.lastIndexOf("bin") + 4,pathName.lastIndexOf("."));
newName = newName.replaceAll("\\\\", "\\.");
newName = newName.replaceAll("/", "\\.");
return newName;
}
/**
*
* @param className 这是包名路径
* @return 返回值是首字母小写的类名例如:userService
*/
public static String parseBeanName(String className) {
int index = className.lastIndexOf('.') + 1;
className = className.substring(index);
String beanName = className.toLowerCase();
beanName = beanName.substring(0,1) + className.substring(1);
return beanName;
}
}
第七步:TestUser
这是具体的操作的每个对象,也就是每个客户.
1.获取当前类的路径.
2.创建BeansFactory对象.
3.给对象中Map字段赋值
4.依赖注入
5.通过key获取容器Map中的对象.
6.调用对象的方法
public class RunApp {
public static void main(String[] args) throws Exception {
//创建一个容器对象
ComponentScan comp = new ComponentScan();
//获取当前类的路径
String path = RunApp.class.getResource("/").getPath();
String pathName = path.substring(1);
//给容器初始化赋值
comp.setBeans(pathName);
//这是给容器初始化依赖注入,必须放在容器初始化之后执行.
comp.inject();
UserDao ud = comp.getValue("userDao");
UserService us = comp.getValue("userService");
UserController uc = comp.getValue("userController");
System.out.println(uc.seletList());
}
}