JavaAnnotation和反光简化开发

Java,Part I

自作者并不是在卖弄本人的塞尔维亚语有稍许的伟大,只不过对Annotation那贰回的诠释真的很烦躁,“表明”和“注释”那多个对Annotation的翻译小编听着不爽,所以全文都用Annotation来代表。

Part II

相信Java的开发职员对Annotation这么些名词一定是那么些的耳熟能详了,方今恒河沙数优质的开源框架,都会提供了Annotation的支撑。如Spring、Hibernate、JUnit4等。可是那又是为何那么多的程序员都喜爱于Annotation的使用啊?笔者个人的原故是因为她实在的简化了大家的操作,就算那样做使得代码和配备的分手难以达成。

Part III

下边大家就用三个权力控制的例子来声明1(Wissu)下,如何使用Annotation来简化我们的开发

料想效应:

  1. 对此每种用户都设定贰个相应的权力。

  2. 各种Dao的操作都投入对权力的检讨。权限不足则抛出安全相当。

思考:

一.
Dao层的方法只关怀Dao的操作,对于权力的检查则不须要关注。因而大家能够用AOP来兑现对权力的反省(在Java中使用动态代理来促成),达成权力检查和Dao操作的解耦。

二.
种种用户都要有相应的权力,而且每种用户的操作都以在分歧的线程上进展,因为大家必供给提供1个用户的权位上下文(RoleContext)来提供对权力的装置和获取。

3.
对于Dao层的落实能够接纳面向接口的编码格局,达成各层之间的解耦。由于各种Dao层所对应的兑现类唯有七个,因而,大家得以把达成类的音信作为元数据写入Dao接口中,所以那边最适合用Annotation来贯彻。

四.
Dao层的章程所须要的权力新闻与落成非亲非故,因而那里也得以把权限的音信作为艺术的元数据写入,所以那边也不行合乎用Annotation来实现。

Part IV

第3大家把项目基本的作风搭建:

package com.gzmu.annotation.dao;

public interface BaseDao { }

package com.gzmu.annotation.dao;

import com.gzmu.annotation.annotation.Implement;

import com.gzmu.annotation.annotation.Permission;

import com.gzmu.annotation.dao.impl.UserDaoImpl;

import com.gzmu.annotation.util.Role;

@Implement(UserDaoImpl.class)

public interface UserDao extends BaseDao {



   @Permission({Role.ADMINISTRATOR, Role.SYSTEM})

   void save();



   @Permission(Role.SYSTEM)

   void delete();



   @Permission({Role.USER, Role.ADMINISTRATOR, Role.SYSTEM})

   void query();



}

package com.gzmu.annotation.dao.impl;

import com.gzmu.annotation.dao.UserDao;

public class UserDaoImpl implements UserDao {



   @Override

   public void save() {

       System.out.println("UserDaoImpl.save()");

   }



   @Override

   public void delete() {

       System.out.println("UserDaoImpl.delete()");

   }



   @Override

   public void query() {

       System.out.println("UserDaoImpl.query()");

   }



}

RoleContext作为二个提供用户权限上下文的单元存在,使用枚举来完结单例情势,ThreadLocal提供了对近期线程权限数据的访问。

package com.gzmu.annotation.context;

import com.gzmu.annotation.util.Role;

public enum RoleContext {



   INSTANCE;



   private ThreadLocal<Role> role = new ThreadLocal<Role>();



   public Role getCurrentRole() {

       return role.get();

   }



   public void setCurrentRole(Role role) {

       this.role.set(role);

   }



}

Implment用来钦命Dao接口对应的落实类。

package com.gzmu.annotation.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import com.gzmu.annotation.dao.BaseDao;

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Implement {



   Class<? extends BaseDao> value();



}

Permission用于钦定Dao层的办法的可访问的人手的拜访权限。

package com.gzmu.annotation.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import com.gzmu.annotation.util.Role;

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface Permission {



   Role[] value();



}

到这边,这几个宗旨的主义就搭建完结了。接下来,大家将要起来使用动态代理、反射以及Annotation来贯彻对权力的反省。

Part V

下边我们就要详细的解释一下以下的代码:

DaoProxyFactory.newRoleDaoProxy():

一.
我们提供五个简便的工厂,用于生产二个代理对象。传入3个急需代理的接口,用于发生完结该接口的代办对象。

二.
出于我们的接口上使用Implement这几个Annotation来内定那些接口所对应的完结类,所以大家得以获取这些实现类会创造叁个事实上被代理的对象。

RoleInvocationHandler

  1. 顾名思义,那几个类正是用来做权限决定的,那些类实现了InvocationHandler。

二.
因为大家早已在接口上定义了怎么着措施对应怎么着被允许实施那些方法的权限,因而大家能够经过method.getAnnotation(Permission.class)那个法子来赢得权限的新闻。

三.
迭代方法的允许权限,并与当前线程用户的权杖做对比,假诺发现双方对等,表达当前用户的权力与艺术执行的权柄1致,因而跳出循环,执行outter标签前边的办法,允许用户执行。

四.
迭代实现后,当前线程用户的权柄没有与格局中定义的权柄壹致,表明用户无权执行这样的操作,由此跑出平Ante别。

package com.gzmu.annotation.util;

import java.lang.annotation.AnnotationFormatError;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import com.gzmu.annotation.annotation.Implement;

import com.gzmu.annotation.annotation.Permission;

import com.gzmu.annotation.context.RoleContext;

import com.gzmu.annotation.dao.BaseDao;

public abstract class DaoProxyFactory {



   @SuppressWarnings("unchecked")

   public static <T> T newRoleDaoProxy(Class<T> dao) {

       Implement implAnnotation = dao.getAnnotation(Implement.class);



       if (implAnnotation == null)

           throw new AnnotationFormatError("该接口未定义实现类的注解");



       BaseDao implClass = null;

       try {

           implClass = implAnnotation.value().newInstance();

       } catch (Exception e) {

           throw new RuntimeException("该接口所定义的实现类不能被实例化", e);

       }



       return (T) Proxy.newProxyInstance(

               DaoProxyFactory.class.getClassLoader(),

               new Class<?>[] { dao },

               new RoleInvocationHandler(implClass)

       );

   }



   private static final class RoleInvocationHandler implements InvocationHandler {

       private BaseDao target;



       public RoleInvocationHandler(BaseDao target) {

           this.target = target;

       }



       @Override

       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

           Permission permitAnnotation = method.getAnnotation(Permission.class);



           outter:

           if (permitAnnotation != null) {

               Role currentRole = RoleContext.INSTANCE.getCurrentRole();

               for (Role permitRole : permitAnnotation.value()) {

                   if (permitRole.equals(currentRole))

                       break outter;

               }

               throw new SecurityException("当前用户不允许执行此操作");

           }



           return method.invoke(target, args);

       }



   }



}

Part VI

因此这一个事例,我们能够见到,用Annotation来简化我们的开发是如此的简单,世界是那般的美好。很多的程序员都认为学习Annotation是一种负担,可能说XML能够完全取代Annotation的留存。但是自身以为,一个事物的存在,必然有她的股票总市值,未有其余的三个东西是力所能及完全代替其余二个事物。与其在作无谓的争议,比不上花时间去商量什么更加好的利用?而且Annotation的大军这么些在持续的扩张,这便是壹种最佳的表明。

原稿地址:http://www.verydemo.com/demo\_c89\_i223660.html

相关文章