Part I

本人并不是在卖弄自己的阿尔巴尼亚语有稍许的伟大,只但是对Annotation那五遍的解说真的很烦躁,“注脚”和“注释”那三个对Annotation的翻译我听着不爽,所以全文都用Annotation来代表。

Part II

相信Java的开发人士对Annotation这些名词一定是丰富的精晓了,近年来无数大好的开源框架,都会提供了Annotation的支撑。如Spring、Hibernate、JUnit4等。不过这又是为什么那么多的程序员都热衷于Annotation的使用呢?我个人的来头是因为他确实的简化了大家的操作,固然如此做使得代码和配置的分开难以落成。

Part III

下边大家就用一个权力决定的事例来证爱他美(Aptamil)下,怎样XML,使用Annotation来简化我们的开发

预料效益:

  1. 对于每个用户都设定一个应和的权力。

  2. 各类Dao的操作都到场对权力的检查。权限不足则抛出安全至极。

思考:

1.
Dao层的措施只关注Dao的操作,对于权力的反省则不需求关心。由此我们得以用AOP来兑现对权力的检讨(在Java中使用动态代理来促成),落成权力检查和Dao操作的解耦。

2.
各类用户都要有相应的权柄,而且每个用户的操作都是在不相同的线程上进展,因为我们亟须要提供一个用户的权位上下文(RoleContext)来提供对权力的装置和获取。

3.
对此Dao层的兑现可以利用面向接口的编码格局,已毕各层之间的解耦。由于每个Dao层所对应的落到实处类唯有一个,由此,我们可以把落成类的音信作为元数据写入Dao接口中,所以那里最契合用Annotation来落实。

4.
Dao层的主意所急需的权柄信息与落到实处毫无干系,由此那里也足以把权限的音讯作为艺术的元数据写入,所以那里也要命相符用Annotation来贯彻。

Part IV

率先大家把品种基本的气派搭建:

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():

1.
大家提供一个粗略的厂子,用于生产一个代理对象。传入一个亟待代理的接口,用于暴发完结该接口的代理对象。

2.
是因为大家的接口上使用Implement这么些Annotation来指定这么些接口所对应的已毕类,所以我们可以赢得这么些完毕类会成立一个其实被代理的目标。

RoleInvocationHandler

  1. 顾名思义,那个类就是用来做权限控制的,这一个类完毕了InvocationHandler。

2.
因为我们曾经在接口上定义了怎么样措施对应什么被允许实施这些艺术的权杖,由此大家得以因此method.getAnnotation(Permission.class)那个方法来取得权限的消息。

3.
迭代方法的同意权限,并与眼前线程用户的权杖做相比,如果发现相互对等,表明当前用户的权柄与艺术执行的权能一致,由此跳出循环,执行outter标签后边的方法,允许用户执行。

4.
迭代做到后,当前线程用户的权能没有与方法中定义的权能一致,表明用户无权执行那样的操作,因此跑出安全非常。

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

相关文章

网站地图xml地图