控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。——摘自百度百科
演示类:
import java.util.Map;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
/**
* 演示类
* @author student
*/
public class Demo {
// 对象字符串数组
private static String[] classNames = { "test_accocation.UserUI", "test_accocation.UserDaoImpl" };
// 用于存储字符串解析的对象
private static Map
map = new HashMap<>();
public static void main(String[] args) throws Exception {
init();
UserUI ui = (UserUI)getBean("ui");
ui.login();
}
/**
* 初始化函数 用于将根据字符串创建的对象解析后放入Map中
*
* @throws Exception
*/
private static void init() throws Exception {
// 遍历数组
for (String className : classNames) {
// 使用Class类通过字符串表示的类名获取对应类文件
Class clazz = Class.forName(className);
// 使用类文件新建对象
Object obj = clazz.newInstance();
// 对象存入Map[键:注解属性值,值:该注解属性值所标注的类对象]
// ------|
<强制转换以获得旗下方法>
|<----获取此类的注解---->|<---获取注解类型:类注解---->|<-获取属性值->|
<值>
|
map.put(((MyTypeAnnotation) clazz.getAnnotation(MyTypeAnnotation.class)).strType(), obj);
}
for (String key : map.keySet()) {
System.out.println(key + "\t" + map.get(key));
}
}
/**
* 使用反射与递归获取对象
*
* @param name
* @return obj
* @throws Exception
* @throws NoSuchMethodException
*/
private static Object getBean(String key) throws Exception {
Object obj = null;
// 依据传入的字符串类型键得到对象值
obj = map.get(key);
// 匹配判断
if (obj != null) {
// 获取对象的类
Class clazz = obj.getClass();
// 使用反射获取该类所有字段
Field[] fs = clazz.getDeclaredFields();
// !第一次迭代终止处!
// 遍历这些字段
for (Field f : fs) {
// 获取字段注解对象
MyFieldAnnotation myFieldAnn = f.getAnnotation(MyFieldAnnotation.class);
// 判断对象是否为空
if (myFieldAnn != null) {
// 获得注解属性,字符串处理得到对应类set方法名
// -----------------|<-前缀->|<-------------获取首字母并大写---------------->|<----获取无首字母字符串------>|
String methodName = "set" + f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1);
// 获得set方法:
// -------------|<--反射获取方法-->|<--方法名-->|<---参数类型--->|
Method method = clazz.getMethod(methodName, f.getType());
//<--调用方法-->|
<方法对象>
|
<强转目标类型.强制转换>
|<-----递归:getBean("dao")----->| method.invoke(obj, f.getType().cast(getBean(myFieldAnn.strField()))); } } } return obj; } }
UI类:
import java.util.Scanner;
/**
* UI类
* 处理用户交互
* @author student
*
*/
//设置自定义类注解 -ui-
@MyTypeAnnotation(strType="ui")
public class UserUI {
//设置自定义字段注解。注意此处标签与UserDao实现类UserDaoImpl中类注解相匹配
@MyFieldAnnotation(strField="dao")
private UserDao dao;//避免new关键字
/**
* 设置UserDaoImpl对象
* @param dao
*/
public void setDao(UserDao dao){
this.dao = dao;
}
/**
* 交互
*/
public void login(){
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String userName = sc.next();
System.out.println("请输入密码:");
String pwd = sc.next();
//判断数据是否合法
//交给Dao中方法处理
User user = new User(userName, pwd);
if(dao.login(user)){
System.out.println("登陆成功");
}else{
System.out.println("用户名或密码错误");
}
sc.close();
}
}
UserDao接口:
/**
* 用户数据访问接口
* DAO (Data Access Object) 数据访问对象
* @author student
*
*/
public interface UserDao {
boolean login(User user);
}
UserDao实现类:
/**
* 用户数据实现类
* @author student
*
*/
//添加自定义类注解
@MyTypeAnnotation(strType="dao")
public class UserDaoImpl implements UserDao{
/**
* 登陆判断
*/
@Override
public boolean login(User user) {
if(user.getUserName().equals("admin")
&&
user.getPwd().equals("123456")){
return true;
}
return false;
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//源注解:注解的注解:@Retention @Target @Document @Inherited四种。
@Target(ElementType.TYPE)//设置注解的作用范围
@Retention(RetentionPolicy.RUNTIME)//设置注解的作用时间
public @interface MyTypeAnnotation {
String strType();
}
自定义字段注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyFieldAnnotation {
String strField();
}
User类略,内涵属性如下:
private String userName;
private String pwd;
同时与其构造器与getset方法。
在使用时需特别注意相关注释属性的匹配:
Class UserDaoImpl:
@MyTypeAnnotation(strType="dao")
public class UserDaoImpl implements UserDao{......}
Class UserUI:
@MyFieldAnnotation(strField="dao")
private UserDao dao;