内省反射机制作用——通过注解实现判断功能

注解

注解的作用?

注解是一个约定,将我们一些要做的有规律的事情声明为一个注解,然后通过反向解析来实现功能,达到封装解耦的目的,注解本身没有任何含义。
需要我们赋予它含义并对这个目标实现代码

我们这里利用注解实现非空、密码位数长度是否满足条件的判断


代码案例

User对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @NotNull
    private String username;
    @NotNull
    @Length(mini = 6,max = 16)
    private String password;
    private String address;
}
非空注解
/**
 * 我们赋予它被这个注解修饰的变量的值不能为null
 * 这类必须使用Retention,否则注解在运行的时候就会被擦除,导致失败
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNull {
}
长度判断注解
//密码长度判断
@Retention(RetentionPolicy.RUNTIME)
public @interface Length {
    int mini();//声明一个方法,返回int类型,当我们通过调用这个方法的时候,会返回我们指定的值
    int max();
}
工具类【重点】

主要用来判断对象的属性是否满足要求

public class MyAnnonationUtils {
    public static void inject(Object o) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
        //我们判断指定对象的一些属性状态,比如不能为空,或者长度在某个范围(8-16),是不是一个手机号等等
        //我们需要先指定这个变量的要求是什么,提前定义这个标准是什么
        //我们通过注解方式来对这个标准进行声明,比如被注解为notnull的标记就是不能为空
        //过程:获取对象所有的变量,然后看看每个变量的要求是什么,然后根据这个要求去做判断,比如不能为空,也就是获取到每个变量的值,然后进行非空判断
        Class<?> aClass = o.getClass();
        //反射获取变量
        Field[] fields = aClass.getDeclaredFields();
        //因为我们不知道每个变量的要求是什么,所以需要遍历
        for (Field field : fields) {
            //拿到变量后看要求是什么,就是拿到注解
            NotNull notNull = field.getAnnotation(NotNull.class);//获取到这个变量上的notnull的代理对象
            Length length = field.getAnnotation(Length.class);

            //说明变量是有不能为空的注解的,我们需要获取到这个变量的值来进行判断
            //因为私有变量不能直接获取,我们需要强制访问,我们应该要调用的是get方法
            //通过属性描述来获取到制定变量的对应描述,参数1表示属性名字,参数2表示从哪个类获取属性
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), aClass);
            Method readMethod = propertyDescriptor.getReadMethod();//获取get方法

            //判断是否有这个注解
            if (notNull != null) {
                if (readMethod != null) {
                    //通过调用指定对象的这个get方法获取到这个对应的变量的值
                    Object value = readMethod.invoke(o);
                    if(value==null) {
                        System.out.println(field.getName() + "值为空");
                    }
                }
            }

            if (length != null) {
                int max = length.max();
                int mini = length.mini();
                if (readMethod != null) {
                    Object value = readMethod.invoke(o);
                    if (value == null || value.toString().length()<mini || value.toString().length()>max) {
                        System.out.println(field.getName() + "不符合要求");
                    }
                }
            }
        }
    }
}
测试类
public class TestMain {
    public static void main(String[] args) throws IllegalAccessException, IntrospectionException, InvocationTargetException {
        User user = new User();
        user.setUsername("鸣人");
        user.setPassword("123456");
        MyAnnonationUtils.inject(user);
        System.out.println(user);
    }
}

Spring的注解使用

/**
 * Created by jackiechan on 19-11-4/下午2:17
 *  这个类是一个配置类,专门用于配置对象,用于取代我们之前编写的XML
 *  文档
 * @Author jackiechan
 */
@Configuration //声明当前是一个配置类
@PropertySource(value = {"classpath:jdbc.properties"})//用于取代   <context:property-placeholder location="classpath:jdbc.properties"/>
@ComponentScan(basePackages = {"com.qianfeng.spring"})//用于取代 <context:component-scan base-package="com.qianfeng.spring"/>,如果不写参数,代表扫描当前类所在的包以及子包
public class MyConfiguration {
    @Value("${jdbc.username}")//专门给字符串属性赋值的,从配置文件中查找指定属性并设置
    private String username;

    @Bean //用于取代bean标签的一个注解,当spring扫描到这个注解的时候会创建这个对象
    public DataSource dataSource1() {
        System.err.println("username======>"+username);
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername(username);
        return dataSource;
    }

    @Bean //用于取代bean标签的一个注解,当spring扫描到这个注解的时候会创建这个对象
    public DataSource dataSource2() {
        DataSource dataSource = new DruidDataSource();
        return dataSource;
    }

    //当我们使用bean注解创建对象的时候,参数 spring会自动查找并注入过来,首要查询条件,是根据类型和形参的名字查找,如果参数对应类型的对象有多个,首选会根据形参的名字去查找id为这个值的对象
    //当这个类型的对象有多个,但是没有与形参名字相同的id的对象 则报错,提示找到了多个对象
    @Bean
    DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource2) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        System.err.println("dasdasdasdad====>"+dataSource2);
        dataSourceTransactionManager.setDataSource(dataSource2);
        return dataSourceTransactionManager;
    }

    //@Qualifier 指定对象的id, 也就是查找DataSource类型的对象并且id是dataSource2
    @Bean
    DataSourceTransactionManager dataSourceTransactionManager2(@Qualifier("dataSource2") DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        System.err.println("dasdasdasdad====>"+dataSource);
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

    @Bean("mingzi") //参数mingzi代表创建后的对象的id叫minghzi
    public DataSource suibian() {
        DataSource dataSource = new DruidDataSource();
        return dataSource;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值