实现@Service、@Autowired、@Transactional注解类

什么是注解

注解可以用来修饰类,方法,属性等,可以看做是一个特殊的标记,程序在编译或运行时检测到这些标记,从而进行一些特殊的操作。

注解的基本元素

1、修饰符,注解的修饰符必须是public,不写默认为public
2、关键字@interface
3、注解名称
4、注解内容
例如:

public @interface Service {
    String value() default "";
}

元注解

元注解可以用来修饰注解
一般注解用到的元注解有两个@Target和@Retention

@Target

用来表明该注解可以修饰的类型与范围
ElementType.TYPE
应用于类、接口(包括注解类型)、枚举
ElementType.FIELD
应用于属性(包括枚举中的常量)
ElementType.METHOD
应用于方法
ElementType.PARAMETER
应用于方法的形参
ElementType.CONSTRUCTOR
应用于构造函数
ElementType.LOCAL_VARIABLE
应用于局部变量
ElementType.ANNOTATION_TYPE
应用于注解类型
ElementType.PACKAGE
应用于包
ElementType.TYPE_PARAMETER
1.8版本新增,应用于类型变量)
ElementType.TYPE_USE
1.8版本新增,应用于任何使用类型的语句中

Retention

用于生命周期
RetentionPolicy.SOURCE
编译时被丢弃,不包含在类文件中
RetentionPolicy.CLASS
JVM加载时被丢弃,包含在类文件中,默认值
RetentionPolicy.RUNTIME
由JVM 加载,包含在类文件中,在运行时可以被获取到

自定义注解实现

我们根据以上注解的定义和属性来自我实现@Service@Autowired@Transactional功能
我们将原来的一个转账的demo基础上进行修改(详情:见博客 自定义Ioc/Aop)
我们之前的demo是通过读取beans.xml配置文件,实例化bean,通过类中的set方法,对其属性进行依赖注入,现在我们将通过@Service注解来实现实例化bean和通过@Autowired注解实现依赖注入,最后通过@Transactional注解实现事务控制

声明注解

@Service

// 作用于类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
    String value() default "";
}

@Autowired

// 作用于属性
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowried {
    boolean value() default true;
}

@Transactional

// 作用于类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {

}

改造demo

文件目录
在这里插入图片描述

我们首先看一下beans.xml文件,对文件中的bean添加@Service注解,然后对beans.xml文件中的property标签对应的属性,添加@Autowired注解并且注释掉对应的set方法
在这里插入图片描述
接着在我们要测试的方法对应的类上添加@Transactional注解,用来测试事务管理
例如:
在这里插入图片描述
接下来是重点,改造BeanFactory

public class BeanFactory {
    public static Map<String,Object> map=new HashMap<>();
    // annotation 版本
    static {
        // 扫描bank文件夹下的类
        Reflections reflections = new Reflections("bank");
        try{
            // 获取带有Service注解的类
            Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(Service.class);
            typesAnnotatedWith.forEach(beanService->{
                try {
                    // 实例化对象,并存入map中,以便之后使用
                    Object o = beanService.newInstance();
                    // 获取@Service value值,如果没有赋值默认是""
                    Service annotation = beanService.getAnnotation(Service.class);
                    String value = annotation.value();
                    // 判断,如果我们没有为类取别名,就读取类名
                    if(StringUtils.isEmpty(value)){
                        String name= beanService.getSimpleName();
                        // 判断是否是接口实现类,如果是用接口类名作为key,这样如果更换实现类的时候,由于我们使用接口类名作为key,
                        // 只需要将@service注解到新的实现类上,我们同样可以使用接口类名调用的到,不需要其他操作
                        Class<?>[] interfaces = beanService.getInterfaces();
                        if(interfaces.length>0){
                          name=interfaces[0].getSimpleName();
                        }
                        // 将类名首字母小写,统一key的格式
                        value=(new StringBuilder()).append(Character.toLowerCase(name.charAt(0))).append(name.substring(1)).toString();
                    }

                    if (map.containsKey(value)){
                        System.out.println("@service注解value命名不能重复");
                    }else {
                        // 注入到map中
                        map.put(value,o);
                    }
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });
            // 通过反射获取属性
            if(!map.isEmpty()){
                for(Map.Entry<String, Object> a: map.entrySet()){
                    Object value = a.getValue();
                    Class<?> aClass = value.getClass();
                    // 使用反射技术,获取到类的全部属性
                    Field[] declaredFields = aClass.getDeclaredFields();
                    for (int i = 0; i <declaredFields.length; i++) {
                        Field declaredField = declaredFields[i];
                        // 判断属性是否使用@Autowired注解
                        if(declaredField.isAnnotationPresent(Autowried.class)){
                            // 暴力访问
                            declaredField.setAccessible(true);
                            // 获取属性对应的对象
                            Object o = map.get(declaredField.getName());
                            // 为属性赋值
                            declaredField.set(value,o);
                        }
                    }

                }
            }
        }catch (Exception e){
              System.out.println("BeanFactiony e"+e.getMessage());
        }
    }

    public static Object getBean(String name){
        Object o = map.get(name);
        return o;
    }

修改动态代理ProxyFactory

@Service
public class ProxyFactory {
    @Autowried
    TransationManager transationManager;
    // jdk动态代理
public Object getJDKProxy(Object object){
    // 创建动态代理对象
    return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
            Class<?> aClass = object.getClass();

            if(aClass.isAnnotationPresent(Transactional.class)){
                // 使用事务管理注解
                try{
                    // 打印被代理的对象
                    System.out.println(object.getClass());
                    // 打印被代理对象的执行方法
                    System.out.println(method.getName());
                    // 答应被代理对象的方法参数
                    for (int i = 0; i <objects.length; i++) {
                        System.out.println(objects[i].toString());
                    }
                    // 开启手动提交事务
                    transationManager.beginTransation();
                    // 执行方法
                    Object invoke = method.invoke(object, objects);
                    // 提交事务
                    transationManager.commitTransation();
                    return invoke;
                }catch (Exception e){
                    // 回滚事务
                    System.out.println("执行回滚");
                    transationManager.rollbackTransation();
                    return null;
                }
            }else{
                // 不使用事务管理
                Object invoke = method.invoke(object, objects);
                return invoke;
            }

        }
    });
}
// Cglib动态代理
public Object getCglib(Object object){
    return Enhancer.create(object.getClass(), new MethodInterceptor() {
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            Class<?> aClass = object.getClass();

            if(aClass.isAnnotationPresent(Transactional.class)){
                try{
                    // 开启手动提交事务
                    transationManager.beginTransation();
                    // 执行方法
                    Object invoke = method.invoke(object, objects);
                    // 提交事务
                    transationManager.commitTransation();
                    return invoke;
                }catch (Exception e){
                    transationManager.rollbackTransation();
                    return null;
                }
            }else{
                Object invoke = method.invoke(o, objects);
                return invoke;
            }
        }
    });
}
public Object getProxy(Object object){
    // 判断走那种动态代理
    Class<?> aClass = object.getClass();
    Class<?>[] interfaces = aClass.getInterfaces();
    if(interfaces.length>0){
        // 使用jdkProxy动态代理
        Object jdkProxy = getJDKProxy(object);
        return jdkProxy;
    }else {
        // 使用cglib动态代理
        return getCglib(object);
    }
}
}

测试

    @Test
    public void annotationTest() throws SQLException {
        ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
        BankService bankService = (BankService) BeanFactory.getBean("bankService");
        BankService proxy = (BankService) proxyFactory.getProxy(bankService);
        Boolean transfer = proxy.transfer("6029621011001", "6029621011000", 100);
    }

执行前
在这里插入图片描述
执行后
在这里插入图片描述
在这里插入图片描述
事务测试
在这里插入图片描述
测试前
在这里插入图片描述
测试后
在这里插入图片描述
在这里插入图片描述

回滚成功!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值