关于python中装饰器与java中注解的区别

学过java的同学第一次在python中看到装饰器修饰函数或类时,第一时间想到的就是java中注解,如@Resource 可能会觉得它们是一样的,从我的理解来说,其实是完全不一样的两个东西。它们形似而神不同。

相同点

它们的作用都是一样的,可以通过它们在不改变原程序代码的情况下,给程序增加一些新的功能,实现AOP。

不同点

注解在文档中的解释是一个‘’标志‘’它的本质是用来给java编译器“看”的注释,在java程序运行时,通过反射查找特定的‘’标志‘’,将此标志作为判断条件,做一些操作;

装饰器的本质是一个函数,闭包函数,将被装饰函数的地址,一般用与被装饰函数相同的名字‘’李代桃僵‘’,调用的其实是装饰器函数反回的函数地址。

看看它们的使用吧
装饰器的使用
import time


# 定义一个装饰器,增加打印程序运行时间的功能
# 小提示,python是解释性语言,从上而下执行代码,装饰器要写在被装饰函数的前面
def outter(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)  # 解构
        stop = time.time()
        print(stop - start)
        return res, stop - start  # 返回被装饰对象的返回值

    return wrapper


@outter  # 在被装饰对象正上方单独一行写@装饰器名(语法糖),等同于index=outter(index)
def index(x, y):
    time.sleep(3)
    print("index %s,%s" % (x, y))


if __name__ == '__main__':
    res = index(1, 3)
    print(res)

程序运行结果

index 1,3
3.0063154697418213
(None, 3.0063154697418213)

注解的使用

模拟spring创建单例和多例对象

1. 定义一个扫描注解

ComponentScan

package com.zhaojun.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义扫描路径注解
 */
@Retention(RetentionPolicy.RUNTIME)//注解的作用时间,程序运行时
@Target(ElementType.TYPE)//注解使用范围
public @interface ComponentScan {
    String value() default "";
}
2. 定义一个配置类

AppConfig

package com.zhaojun.service;

import com.zhaojun.spring.ComponentScan;

@ComponentScan("com.zhaojun.service")
public class AppConfig {
}
3. 定义一个Bean注解

Component

package com.zhaojun.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义Bean注解
 */
@Retention(RetentionPolicy.RUNTIME)//运行时
@Target(ElementType.TYPE)//注解使用范围
public @interface Component {
    String value() default "";
}
4. 定义一个Scope注解
package com.zhaojun.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 单例Bean或多例Bean
 */
@Retention(RetentionPolicy.RUNTIME)//运行时
@Target(ElementType.TYPE)//注解使用范围
public @interface Scope {
    String value() default "";
}
5. 定义一个类,模拟spring容器
package com.zhaojun.spring;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 自定义Spring容器
 */
public class ZhaojunApplicationContext {
    private Class configClass;
    private ConcurrentHashMap<String,BeanDefinition> beanDefinitipnMap=new ConcurrentHashMap<>();
    private ConcurrentHashMap<String,Object> singleObjects=new ConcurrentHashMap<>();//单例Bean池

    public ZhaojunApplicationContext(Class configClass) {
        this.configClass = configClass;

        //扫描
        if(configClass.isAnnotationPresent(ComponentScan.class)){
            ComponentScan componentScanAnnotation = (ComponentScan)configClass.getAnnotation(ComponentScan.class);
            //获取注解中配置的路径 com.zhaojun.service
            String path = componentScanAnnotation.value();
            path=path.replace(".","/");//com/zhaojun/service

            ClassLoader classLoader = ZhaojunApplicationContext.class.getClassLoader();
            //从classpath中获取class文件路径
            URL resource = classLoader.getResource(path);

            File file = new File(resource.getFile());//获取到指定文件夹或文件
            if (file.isDirectory()){
                File[] files = file.listFiles();
                for (File f:files){
                    String fileName = f.getAbsolutePath();
                    if (fileName.endsWith(".class")){
                        //转换全类名
                        URL resource1 = ZhaojunApplicationContext.class.getResource("/");
                        String path1 = resource1.getPath();
                        String className = fileName.substring(path1.length()-1); //com\zhaojun\service\AppConfig.class
                        //拿捏类名 com.zhaojun.service.AppConfig
                        String replace = className.substring(0, className.indexOf(".class")).replace("\\", ".");

                        try {
                            Class<?> clazz = classLoader.loadClass(replace);
                            if (clazz.isAnnotationPresent(Component.class)){
                                //获取bean的名字
                                Component component = clazz.getAnnotation(Component.class);
                                String beanName = component.value();
                                //BeanDefinition
                                BeanDefinition beanDefinition=new BeanDefinition();
                                beanDefinition.setType(clazz);
                                //判断多例还是单例Bean
                                if (clazz.isAnnotationPresent(Scope.class)) {
                                    Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
                                    String scop = scopeAnnotation.value();
                                    beanDefinition.setScope(scop);
                                }else{
                                    beanDefinition.setScope("singleton");
                                }
                                //保存Bean
                                beanDefinitipnMap.put(beanName,beanDefinition);
                            }
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

        //实例化单例Bean
        for (String beanName : beanDefinitipnMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitipnMap.get(beanName);
            if (beanDefinition.getScope().equals("singleton")){
                Object bean = createBean(beanName,beanDefinition);
                singleObjects.put(beanName,bean);
            }
        }

    }
    //创建对象
    private Object createBean(String beanName,BeanDefinition beanDefinition){
        Class clazz = beanDefinition.getType();
        try {
            Object instance = clazz.getConstructor().newInstance();//调无参构造创建实例
            return instance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }
    //自定义getBean方法
    public Object getBean(String beanName){
        BeanDefinition beanDefinition = beanDefinitipnMap.get(beanName);
        if(beanDefinition==null){
            throw new NullPointerException();
        }else{
            String scope = beanDefinition.getScope();
            if(scope.equals("singleton")){
                Object bean = singleObjects.get(beanName);
                if(bean==null){
                    Object o = createBean(beanName, beanDefinition);
                    singleObjects.put(beanName,o);
                }
                return bean;
            }else{
                //多例
                return createBean(beanName, beanDefinition);
            }
        }
    }
}
6. 创建一个类,用来测试
package com.zhaojun.service;

import com.zhaojun.spring.Component;
import com.zhaojun.spring.Scope;

@Component("userService")
@Scope("prototype")
public class UserService {
}
7. 测试
package com.zhaojun.service;

import com.zhaojun.spring.ZhaojunApplicationContext;

public class Test {
    public static void main(String[] args) {
        ZhaojunApplicationContext zhaojunApplicationContext = new ZhaojunApplicationContext(AppConfig.class);

        System.out.println(zhaojunApplicationContext.getBean("userService"));
        System.out.println(zhaojunApplicationContext.getBean("userService"));
        System.out.println(zhaojunApplicationContext.getBean("userService"));
        System.out.println(zhaojunApplicationContext.getBean("userService"));
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值