【Annotation】使用自定义注解实现依赖注入

控制反转(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;


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值