Day54 元注解补充、综合案例、request/response
1.思维导图
2.代码部分
元注解
- @Target
定义
@Target(value = { ElementType.TYPE , ElementType.FIELD , ElementType.METHOD , ElementType.PARAMETER , ElementType.LOCAL_VARIABLE } ) public @interface MyAnnotation01 { String value() default "hello annotation"; }
使用
@MyAnnotation01 public class Demo01 { @MyAnnotation01 private int num = 1; @MyAnnotation01 public static void main(@MyAnnotation01 String[] args) { @MyAnnotation01 int num = 1; } }
- @Retention
定义
@Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation01 { String value() default "hello annotation"; }
@Retention(RetentionPolicy.RUNTIME) public @interface MyTest { String value() default ""; }
- Test01测试类
1 public class Test01 { 2 3 @Test 4 public void test01(){ 5 System.out.println("test01"); 6 } 7 8 @MyTest 9 public void test02(){ 10 System.out.println("test02"); 11 } 12 13 @MyTest 14 public void test03(){ 15 System.out.println("test03"); 16 } 17 18 public void test04(){ 19 System.out.println("test04"); 20 } 21 22 }
- demo类
1 public class Demo02 { 2 3 public static void main(String[] args) { 4 //使用反射,扫描Test01类里面有哪些方法有@MyTest注解 5 //如果有@MyTest注解,就将其执行 6 //如果没有@MyTest注解,不做任何处理 7 8 //1,获取Test01类对应的Class对象 9 Class<Test01> clazz = Test01.class; 10 //2,获取Test01类下所有的方法对象 11 Method[] methods = clazz.getMethods(); 12 //stream流 lambda表达式 13 Arrays.stream(methods).forEach(method -> { 14 //method就是单个方法对象 15 //3,判断方法上是否有@MyTest注解 16 boolean present = method.isAnnotationPresent(MyTest.class); 17 if (present) { 18 //方法上有@MyTest注解,执行方法 19 try { 20 method.invoke(clazz.newInstance()); 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } 24 } else { 25 //方法上没有@MyTest注解 26 } 27 }); 28 } 29 }
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 public @interface JDBCInfo { 4 5 String driverClass() default "com.mysql.jdbc.Driver"; 6 String jdbcUrl() default "jdbc:mysql://localhost:3306/day53"; 7 String user() default "root"; 8 String password() default "root123"; 9 10 }
-
反射读取注解@JDBCInfo中的内容
1 @JDBCInfo(password="1234") 2 public static Connection getConnection() throws Exception{ 3 /** 4 * 获得当前类上的getConnection方法. 5 * 获得该方法上的@JDBCInfo这个注解. 6 * 获得这个注解中的属性的值. 7 * 使用这些值为下面参数设置值. 8 */ 9 // 获得JDBCUtils的类的Class对象. 10 Class clazz = JDBCUtils.class; 11 // 获得getConnection方法: 12 Method method = clazz.getMethod("getConnection", null); 13 // 获得方法上的注解: 14 JDBCInfo jdbcInfo = method.getAnnotation(JDBCInfo.class); 15 // 获得注解中的属性的值: 16 String driverClass = jdbcInfo.driverClass(); 17 String url = jdbcInfo.url(); 18 String username = jdbcInfo.username(); 19 String password = jdbcInfo.password(); 20 // 加载驱动: 21 Class.forName(driverClass); 22 // 获得连接: 23 Connection conn = DriverManager.getConnection(url, username, password); 24 return conn; 25 }
1 @Retention(RetentionPolicy.RUNTIME) 2 public @interface SystemLog { 3 4 String className();//记录类名 5 String methodName();//记录方法名 6 7 }
- 设置@SystemLog中className属性、methodName属性
1 public interface UserDao { 2 3 @SystemLog(className = "com.qfedu.dao.UserDao" , methodName = "addUser") 4 void addUser() throws Exception; 5 6 void deleteUser() throws Exception; 7 8 @SystemLog(className = "com.qfedu.dao.UserDao" , methodName = "updateUser") 9 void updateUser() throws Exception; 10 11 }
- 编写装饰者设计模式
1 public class UserDaoWrapper implements UserDao{ 2 3 private UserDao userDao; 4 5 public UserDaoWrapper(UserDao userDao) { 6 this.userDao = userDao; 7 } 8 9 @Override 10 public void addUser() throws Exception { 11 userDao.addUser(); 12 printLog("addUser"); 13 } 14 15 @Override 16 public void deleteUser() throws Exception { 17 userDao.deleteUser(); 18 printLog("deleteUser"); 19 } 20 21 @Override 22 public void updateUser() throws Exception { 23 userDao.updateUser(); 24 printLog("updateUser"); 25 } 26 27 /** 28 * 日志记录 29 * @param runMethodName 30 */ 31 private void printLog(String runMethodName) throws Exception { 32 //判断接口上对应的方法中是否有@SystemLog注解 33 //获取UserDao接口实现子类的Class对象 34 Class<? extends UserDao> sonClazz = userDao.getClass(); 35 //获取UserDao接口的Class对象 36 Class<?>[] interfaces = sonClazz.getInterfaces(); 37 Class<?> fatherClazz = interfaces[0]; 38 //获取接口中对应的方法对象(addUser方法) 39 Method method = fatherClazz.getMethod(runMethodName); 40 if (null != method) { 41 //判断方法上是否有@SystemLog注解 42 boolean present = method.isAnnotationPresent(SystemLog.class); 43 if (present) { 44 //方法有@SystemLog注解,打印日志 45 SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss"); 46 Date currentDate = new Date(); 47 String currentTimeStr = format.format(currentDate); 48 SystemLog systemLog = method.getAnnotation(SystemLog.class); 49 String className = systemLog.className(); 50 String methodName = systemLog.methodName(); 51 System.out.println(currentTimeStr + " --- " + className + "类中 ---" + methodName + "()方法 --- 运行了"); 52 } 53 } 54 55 } 56 }
1 @Retention(RetentionPolicy.RUNTIME) 2 public @interface SystemLog { 3 4 String className();//记录类名 5 String methodName();//记录方法名 6 7 }
- 设置@SystemLog中className属性、methodName属性
1 public interface UserDao { 2 3 @SystemLog(className = "com.qfedu.dao.UserDao" , methodName = "addUser") 4 void addUser() throws Exception; 5 6 void deleteUser() throws Exception; 7 8 @SystemLog(className = "com.qfedu.dao.UserDao" , methodName = "updateUser") 9 void updateUser() throws Exception; 10 11 }
- 动态代理
1 UserDao userDao = new UserDaoImpl(); 2 UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance( 3 userDao.getClass().getClassLoader(), 4 userDao.getClass().getInterfaces(), 5 new InvocationHandler() { 6 @Override 7 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 8 //获取到接口中方法对象 , 比如 : UserDao接口中addUser方法 9 //之前 10 //先获取实现子类的Class对象 11 //再获取到接口的Class对象 12 //再获取到接口中的方法对象 13 //现在 14 //再获取到接口的Class对象 -- userDao.getClass().getInterfaces(), 15 //再获取到接口中的方法对象 -- Method method 16 //method : 就是接口中的方法对象 17 Object returnValue = null; 18 if (null != method) { 19 boolean present = method.isAnnotationPresent(SystemLog.class); 20 if (present) { 21 //如果有@SystemLog注解 , 执行原有功能 , 打印日志 22 returnValue = method.invoke(userDao, args); 23 String currentTimeStr = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss") 24 .format(new Date()); 25 SystemLog systemLog = method.getAnnotation(SystemLog.class); 26 String className = systemLog.className(); 27 String methodName = systemLog.methodName(); 28 System.out.println(currentTimeStr + " --- " + className + "类中 ---" + methodName + "()方法 --- 运行了"); 29 } else { 30 //如果没有@SystemLog注解, 执行原有功能, 不打印日志 31 returnValue = method.invoke(userDao, args); 32 } 33 } 34 35 return returnValue; 36 } 37 }); 38 39 userDaoProxy.addUser();