注解
注解的作用?
注解是一个约定,将我们一些要做的有规律的事情声明为一个注解,然后通过反向解析来实现功能,达到封装解耦的目的,注解本身没有任何含义。
需要我们赋予它含义并对这个目标实现代码
我们这里利用注解实现非空、密码位数长度是否满足条件的判断
代码案例
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;
}
}