deprecated
很多同学在进行编程学习时缺乏系统学习的资料。本页面基于deprecated内容,从基础理论到综合实战,通过实用的知识类文章,标准的编程教程,丰富的视频课程,为您在deprecated相关知识领域提供全面立体的资料补充。同时还包含 damain、dart、dataset 的知识内容,欢迎查阅!
deprecated相关知识
-
php之Deprecated 问题åDeprecated: Function ereg_replace() is deprecated in G:\wamp\www\class\classindex.php on line 119这是我遇到的问题一下是网友的解决方法,它山之石可以攻玉。错误提示:Deprecated: Function ereg_replace() is deprecated in 根目录\includes\functions\html_output.php on line 19今天安装了一个wampserver2.2c-x32最新版本php5.3.9,apache2.2.21,mysql5.5.20,phpmyadmin3.4.9这些程序版本都比较高的。但php5.3.9版本已经没有ereg_replace()这个函数了,我电脑里面安装的是zencart1.3.9h这个版本还有用这个函数,所以就会出来这个错误,下面来说下解决问题的办法:方法一: 把php版本安装成5.2.x的.方法二: 如果一定要用php5.3.
-
Spring-手写Spring注解版本事务,Spring事物的七大传播行为一、注解 1、什么是内置注解 (1) @SuppressWarnings 再程序前面加上可以在javac编译中去除警告--阶段是SOURCE (2) @Deprecated 带有标记的包,方法,字段说明其过时----阶段是SOURCE (3)@Overricle 打上这个标记说明该方法是将父类的方法重写--阶段是SOURCE 1.1、@Overricle 案例演示 @Override public String toString() { return null; } 1.2、@Deprecated案例演示 表示此方法已被弃用 new Date().parse(""); 如果已被弃用,则在调用时出现删除线
-
java中的注解种类1.jdk自带注解@Override :覆盖父类方法@Deprecated :父类(接口)中标记方法过时@Suppvisewarnings:调用过时的方法的时候会有警告,此注解用来忽略“deprecate”,取消警告2.第三方注解Spring : @Autowired : @Service : @Repository:Mybatis: @InsertProvider: @UpdateProvider: @Options :3.注解的分类(按照运行机制分): 源码注解 : 编译时注解:@Override @Deprecated @Suppvisewarnings 运行时注解:@Autowired 按照来源分: jdk自带注解 第三方注解 自定义注解 元注解:注解的注解
-
Thinking in java 基础之注解Thinking in java 基础之注解 上半部分源码分析,下半部分具体实现 内置注解: java.lang包中(3个) 注解的语法比较简单,除了@符号的使用之外,它基本与Java固有语法一致。Java SE1.5内置了三种标准注解: @Override,表示当前的方法定义将覆盖超类中的方法。 @Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。 @SuppressWarnings,关闭不当编译器警告信息。 元注解:Java.lang.Annotation包中(4个) 上面这三个注解
deprecated相关课程
deprecated相关教程
- 4. 注解的应用 在上一步我们知道了如何声明和定义标签了,那么接下来就是用这个标签,如何把我们定义好的标签贴到指定的代码上。在 Kotlin 中使用注解和 Java 一样。要应用一个注解都是 @注解类名。@Target(AnnotationTarget.FUNCTION)@Retention(value = AnnotationRetention.RUNTIME)annotation class TestAnnotation(val value: Int)//和一般的声明很类似,只是在class前面加上了annotation修饰符class Test { @TestAnnotation(value = 1000) fun test() {//给test函数贴上TestAnnotation标签(添加TestAnnotation注解) //... }}在很多常见的 Java 或 Kotlin 框架中大量使用了注解,比如我们最常见的 JUnit 单元测试框架:class ExampleUnitTest { @Test //@Test注解就是为了告诉JUnit框架,这是一个测试方法,当做测试调用。 fun addition_isCorrect() { assertEquals(4, 2 + 2) }}在 Kotlin 中注解类中还可以拥有注解类作为参数,不妨来看下 Kotlin 中对 @Deprecated这个注解源码定义,以及它的使用。@Deprecated 注解在原来的 Java 基础增强了一个 ReplaceWith 功能.。可以直接在使用了老的 API 时,编译器可以根据 ReplaceWith 中的新 API,自动替换成新的 API。这一点在 Java 中是做不到的,你只能点击进入这个 API 查看源码来正确使用新的 API。//@Deprecated注解比Java多了ReplaceWith功能, 这样当你在调用remove方法,编译器会报错。使用代码提示会自动IntelliJ IDEA不仅会提示使用哪个函数提示替代它,而且会快速自动修正。@Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"), level = DeprecationLevel.ERROR)//定义的级别是ERROR级别的,这样当你在调用remove方法,编译器会报错。@kotlin.internal.InlineOnlypublic inline fun <T> MutableList<T>.remove(index: Int): T = removeAt(index)@Deprecated 注解的 remove 函数使用://Deprecated注解的使用fun main(args: Array<String>) { val list = mutableListOf("a", "b", "c", "d", "e") list.remove(3)//这里会报错, 通过remove函数注解定义,这个remove函数在定义的level是ERROR级别的,所以编译器直接抛错}最后来看下 @Deprecated 注解的定义:@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS)@MustBeDocumentedpublic annotation class Deprecated( val message: String, val replaceWith: ReplaceWith = ReplaceWith(""),//注解类中构造器可以使用注解类作为函数参数 val level: DeprecationLevel = DeprecationLevel.WARNING)@Target()@Retention(BINARY)@MustBeDocumentedpublic annotation class ReplaceWith(val expression: String, vararg val imports: String)注意:注解类中只能拥有如下类型的参数: 基本数据类型、字符串、枚举、类引用类型、其他的注解类(例如Deprecated注解类中的ReplaceWith注解类)
- 2.2 分类 Java 注解可以分为 3 类:由编译器使用的注解:如@Override、@Deprecated、@SupressWarnings等;由工具处理.class文件使用的注解:比如有些工具会在加载class的时候,对class做动态修改,实现一些特殊的功能。这类注解会被编译进入.class文件,但加载结束后并不会存在于内存中。这类注解只被一些底层库使用,一般我们不必自己处理;在程序运行期间能够读取的注解:它们在加载后一直存在于JVM中,这也是最常用的注解。
- 2.1 内置的注解 我们先看一下 Java 提供了哪些内置注解,以及这些注解的作用。(大致了解即可)Java 定义了一套注解,共有 10 个,5 个在 java.lang 包中,剩下 5 个在 java.lang.annotation 包中。2.1.1 用在代码的注解@Override:检查该方法是否正确地重写了父类的方法。如果重写错误,会报编译错误;@Deprecated:标记过时方法。如果使用该方法,会报编译警告;@SuppressWarnings:指示编译器去忽略注解中声明的警告;@SafeVarargs:Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告;@FunctionalInterface:Java 8 开始支持,标识一个匿名函数或函数式接口。2.1.2 用在其他注解的注解此类注解也称为元注解(meta annotation),在下面学习定义注解的时候,我们将会详细讲解。@Retention:标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问;@Documented:标记这些注解是否包含在用户文档中;@Target:标记这个注解应该是哪种 Java 成员;@Inherited:标记这个注解是继承于哪个注解类;@Repeatable:Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
- 2.1 scrapy-redis 中的 RedisSpider 类分析 来看 RedisSpider 类的定义,它位于源码的 spider.py 文件中:# 源码位置:scrapy_redis/spider.py# ...class RedisSpider(RedisMixin, Spider): """Spider that reads urls from redis queue when idle. Attributes ---------- redis_key : str (default: REDIS_START_URLS_KEY) Redis key where to fetch start URLs from.. redis_batch_size : int (default: CONCURRENT_REQUESTS) Number of messages to fetch from redis on each attempt. redis_encoding : str (default: REDIS_ENCODING) Encoding to use when decoding messages from redis queue. Settings -------- REDIS_START_URLS_KEY : str (default: "<spider.name>:start_urls") Default Redis key where to fetch start URLs from.. REDIS_START_URLS_BATCH_SIZE : int (deprecated by CONCURRENT_REQUESTS) Default number of messages to fetch from redis on each attempt. REDIS_START_URLS_AS_SET : bool (default: False) Use SET operations to retrieve messages from the redis queue. If False, the messages are retrieve using the LPOP command. REDIS_ENCODING : str (default: "utf-8") Default encoding to use when decoding messages from redis queue. """ @classmethod def from_crawler(self, crawler, *args, **kwargs): obj = super(RedisSpider, self).from_crawler(crawler, *args, **kwargs) # 设置redis相关信息 obj.setup_redis(crawler) return obj # ...源码中关于该类的说明已经非常清楚了,我们简单翻一下就是:空闲时从 redis 队列中读取 urls 的 spider。来关注 from_crawler() 方法的第二个语句:setup_redis(),其实现代码如下:class RedisMixin(object): """Mixin class to implement reading urls from a redis queue.""" redis_key = None redis_batch_size = None redis_encoding = None # Redis client placeholder. server = None def start_requests(self): """Returns a batch of start requests from redis.""" return self.next_requests() def setup_redis(self, crawler=None): """Setup redis connection and idle signal. This should be called after the spider has set its crawler object. """ if self.server is not None: return if crawler is None: # We allow optional crawler argument to keep backwards # compatibility. # XXX: Raise a deprecation warning. crawler = getattr(self, 'crawler', None) if crawler is None: raise ValueError("crawler is required") settings = crawler.settings # 设置redis_key属性值,如果settings.py中没有设置,就会使用默认的key值 if self.redis_key is None: self.redis_key = settings.get( 'REDIS_START_URLS_KEY', defaults.START_URLS_KEY, ) self.redis_key = self.redis_key % {'name': self.name} # 确保redis_key值不为空 if not self.redis_key.strip(): raise ValueError("redis_key must not be empty") # 获取redis_batch_size的值,并转成int类型 if self.redis_batch_size is None: # TODO: Deprecate this setting (REDIS_START_URLS_BATCH_SIZE). self.redis_batch_size = settings.getint( 'REDIS_START_URLS_BATCH_SIZE', settings.getint('CONCURRENT_REQUESTS'), ) try: self.redis_batch_size = int(self.redis_batch_size) except (TypeError, ValueError): raise ValueError("redis_batch_size must be an integer") # 获取redis_batch_size值 if self.redis_encoding is None: self.redis_encoding = settings.get('REDIS_ENCODING', defaults.REDIS_ENCODING) self.logger.info("Reading start URLs from redis key '%(redis_key)s' " "(batch size: %(redis_batch_size)s, encoding: %(redis_encoding)s", self.__dict__) # 获取server属性,即redis的连接 self.server = connection.from_settings(crawler.settings) # The idle signal is called when the spider has no requests left, # that's when we will schedule new requests from redis queue crawler.signals.connect(self.spider_idle, signal=signals.spider_idle) def next_requests(self): """Returns a request to be scheduled or none.""" use_set = self.settings.getbool('REDIS_START_URLS_AS_SET', defaults.START_URLS_AS_SET) fetch_one = self.server.spop if use_set else self.server.lpop # XXX: Do we need to use a timeout here? found = 0 # TODO: Use redis pipeline execution. while found < self.redis_batch_size: data = fetch_one(self.redis_key) if not data: # Queue empty. break req = self.make_request_from_data(data) if req: yield req found += 1 else: self.logger.debug("Request not made from data: %r", data) if found: self.logger.debug("Read %s requests from '%s'", found, self.redis_key) def make_request_from_data(self, data): """Returns a Request instance from data coming from Redis. By default, ``data`` is an encoded URL. You can override this method to provide your own message decoding. Parameters ---------- data : bytes Message from redis. """ url = bytes_to_str(data, self.redis_encoding) return self.make_requests_from_url(url) def schedule_next_requests(self): """Schedules a request if available""" # TODO: While there is capacity, schedule a batch of redis requests. for req in self.next_requests(): self.crawler.engine.crawl(req, spider=self) def spider_idle(self): """Schedules a request if available, otherwise waits.""" # XXX: Handle a sentinel to close the spider. self.schedule_next_requests() raise DontCloseSpider上面的代码比较简单,也十分容易看懂。关于 setup_redis() 方法:该方法主要是设置 redis 相关信息,同时连接 redis 并得到连接属性 self.server 值;从该方法中我们可以看到在 settings.py 中我们可以设置如下几个参数:REDIS_START_URLS_KEY:设置起始 urls 的 key,前面我们知道没有设置是,默认的 key 是 爬虫名:start_urls,这在代码中也有所体现;if self.redis_key is None: self.redis_key = settings.get( 'REDIS_START_URLS_KEY', defaults.START_URLS_KEY, )# default.py中有START_URLS_KEY = '%(name)s:start_urls'self.redis_key = self.redis_key % {'name': self.name}REDIS_START_URLS_BATCH_SIZE:已经移除了;REDIS_ENCODING: 设置 redis 中的编码类型;REDIS 的相关配置,主要在如下的语句中读取:self.server = connection.from_settings(crawler.settings)我们来跟踪下这个 connection.from_settings() 的代码,位于 connection.py 中:# 源码位置:scrapy_redis/connection.pyimport sixfrom scrapy.utils.misc import load_objectfrom . import defaults# 重要的映射关系,对应着settings.py的SETTINGS_PARAMS_MAP = { 'REDIS_URL': 'url', 'REDIS_HOST': 'host', 'REDIS_PORT': 'port', 'REDIS_ENCODING': 'encoding',}def get_redis_from_settings(settings): params = defaults.REDIS_PARAMS.copy() params.update(settings.getdict('REDIS_PARAMS')) # XXX: Deprecate REDIS_* settings. for source, dest in SETTINGS_PARAMS_MAP.items(): val = settings.get(source) if val: params[dest] = val # Allow ``redis_cls`` to be a path to a class. if isinstance(params.get('redis_cls'), six.string_types): params['redis_cls'] = load_object(params['redis_cls']) return get_redis(**params)# Backwards compatible alias.from_settings = get_redis_from_settingsdef get_redis(**kwargs): # 默认使用defaults.REDIS_CLS,也就是redis.StrictRedis redis_cls = kwargs.pop('redis_cls', defaults.REDIS_CLS) url = kwargs.pop('url', None) if url: return redis_cls.from_url(url, **kwargs) else: return redis_cls(**kwargs)上面的代码非常简单,get_redis_from_settings() 方法会从 settings.py 中读取 REDIS_URL 、REDIS_HOST 、REDIS_PORT 等参数,另外还会额外读取 REDIS_PARAMS 。优先使用 REDIS_URL 配置信息,来看看最核心的建立客户端连接实例的代码:if url: return redis_cls.from_url(url, **kwargs)else: return redis_cls(**kwargs)这里的 redis_cls 正是第三方模块类 redis.StrictRedis,当然我们也可以通过覆盖 default.py 中的 REDIS_PARAMS 参数中的 redis_cls 来选择新的操作 redis 的第三方模块。紧接着,我们注意到前面在改造 Scrapy 爬虫时去掉了 start_requests() 这个方法。在启动 scrapy 爬虫后,爬虫会等到 redis 的 urls 队列中出现相应的起始 url 值,然后获取该 url 开始数据爬取。我们来看看这个过程是如何实现的?RedisSpider 类继承了 RedisMixin 这个 mixin,它是 scrapy-redis 插件爬虫需要单独实现的功能类。该 Mixin 中正好实现了 start_requests() 方法,具体代码如下:# 源码位置:scrapy_redis/spiders.py# ...class RedisMixin(object): # ... def start_requests(self): """Returns a batch of start requests from redis.""" return self.next_requests() # ... def next_requests(self): """Returns a request to be scheduled or none.""" use_set = self.settings.getbool('REDIS_START_URLS_AS_SET', defaults.START_URLS_AS_SET) fetch_one = self.server.spop if use_set else self.server.lpop # XXX: Do we need to use a timeout here? found = 0 # TODO: Use redis pipeline execution. while found < self.redis_batch_size: data = fetch_one(self.redis_key) if not data: # Queue empty. break req = self.make_request_from_data(data) if req: yield req found += 1 else: self.logger.debug("Request not made from data: %r", data) if found: self.logger.debug("Read %s requests from '%s'", found, self.redis_key) def make_request_from_data(self, data): url = bytes_to_str(data, self.redis_encoding) return self.make_requests_from_url(url) # ... 我们没有设置 REDIS_START_URLS_AS_SET 值,所以默认使用 Redis 的列表类型。因此 fetch_one 方法就是 self.server.lpop,对应就是 Redis 中的 lpop (左弹出) 方法。我们的 URL 是使用 lpush 进去了,获取该结果默认使用的是 lpop,因此我们知道先 push 进去的 url 元素就会后 pop 弹出并执行。另外,我们看到,如果 redis 中对应的 urls 队列中存在一个 url 元素后,执行如下操作:req = self.make_request_from_data(data)if req: yield req found += 1else: self.logger.debug("Request not made from data: %r", data)来继续看 self.make_request_from_data() 这个方法:def make_request_from_data(self, data): url = bytes_to_str(data, self.redis_encoding) return self.make_requests_from_url(url)这个 self.make_requests_from_url() 方法其实调用的是 scrapy 模块中的 spider 类中的方法:# 源码位置:scrapy/spiders/__init__.py# ...class Spider(object_ref): # ... def make_requests_from_url(self, url): """ This method is deprecated. """ warnings.warn( "Spider.make_requests_from_url method is deprecated: " "it will be removed and not be called by the default " "Spider.start_requests method in future Scrapy releases. " "Please override Spider.start_requests method instead." ) return Request(url, dont_filter=True)最终我们发现在 scrapy-redis 插件中,它的 RedisSpider 类也有默认的 start_requests() 方法,该方法从 redis 中指定的队列中取出 urls 并封装成 Scrapy 中的 Request 请求并 yield 给 Scrapy 的调度器去调度处理。
- 8.2 Kotlin 中 DCL 实现 在 Kotlin 中有个天然特性可以支持线程安全 DCL 的单例,可以说也是非常非常简单,就仅仅 3 行代码左右,那就是 Companion Object + lazy 属性代理,一起来看下吧。class KLazilyDCLSingleton private constructor() : Serializable {//private constructor()构造器私有化 fun doSomething() { println("do some thing") } private fun readResolve(): Any {//防止单例对象在反序列化时重新生成对象 return instance } companion object { //通过@JvmStatic注解,使得在Java中调用instance直接是像调用静态函数一样, //类似KLazilyDCLSingleton.getInstance(),如果不加注解,在Java中必须这样调用: KLazilyDCLSingleton.Companion.getInstance(). @JvmStatic //使用lazy属性代理,并指定LazyThreadSafetyMode为SYNCHRONIZED模式保证线程安全 val instance: KLazilyDCLSingleton by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { KLazilyDCLSingleton() } }}//在Kotlin中调用,直接通过KLazilyDCLSingleton类名调用instancefun main(args: Array<String>) { KLazilyDCLSingleton.instance.doSomething()}//在Java中调用public class TestMain { public static void main(String[] args) { //加了@JvmStatic注解后,可以直接KLazilyDCLSingleton.getInstance(),不会打破Java中调用习惯,和Java调用方式一样。 KLazilyDCLSingleton.getInstance().doSomething(); //没有加@JvmStatic注解,只能这样通过Companion调用 KLazilyDCLSingleton.Companion.getInstance().doSomething(); }}注意:建议上面例子中添加 @JvmStatic 注解,Kotlin 这门语言可谓是操碎了心,做的很小心翼翼,为了不让 Java 开发者打破他们的调用习惯,让调用根本无法感知到是 Kotlin 编写,因为外部调用方式和 Java 方式一样。如果硬生生把 Companion 对象暴露给 Java 开发者他们可能会感到一脸懵逼。可能大家对 lazy 和 Companion Object 功能强大感到一脸懵,让我们一起瞅瞅反编译后的 Java 代码你就会恍然大悟了:public final class KLazilyDCLSingleton implements Serializable { @NotNull private static final Lazy instance$delegate; //Companion提供公有全局访问点,KLazilyDCLSingleton.Companion实际上一个饿汉式的单例模式 public static final KLazilyDCLSingleton.Companion Companion = new KLazilyDCLSingleton.Companion((DefaultConstructorMarker)null); public final void doSomething() { String var1 = "do some thing"; System.out.println(var1); } private final Object readResolve() { return Companion.getInstance(); } private KLazilyDCLSingleton() { } static {//注意: 可以看到静态代码块中并不是初始化KLazilyDCLSingleton的instance而是初始化它的Lazy代理对象,说明KLazilyDCLSingleton类被加载了, //但是KLazilyDCLSingleton的instance并没有被初始化,符合懒加载规则,那么什么时候初始化instance这就涉及到了属性代理知识了,下面会做详细分析 instance$delegate = LazyKt.lazy(LazyThreadSafetyMode.SYNCHRONIZED, (Function0)null.INSTANCE); } // $FF: synthetic method public KLazilyDCLSingleton(DefaultConstructorMarker $constructor_marker) { this(); } @NotNull public static final KLazilyDCLSingleton getInstance() { return Companion.getInstance();//这里可以看到加了@JvmStatic注解后,getInstance内部把我们省略Companion.getInstance()这一步,这样一来Java调用者就直接KLazilyDCLSingleton.getInstance()获取单例实例 } //Companion静态内部类实际上也是一个单例模式 public static final class Companion { // $FF: synthetic field static final KProperty[] ?delegatedProperties = new KProperty[]{(KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(KLazilyDCLSingleton.Companion.class), "instance", "getInstance()Lcom/mikyou/design_pattern/singleton/kts/KLazilyDCLSingleton;"))}; /** @deprecated */ // $FF: synthetic method @JvmStatic public static void instance$annotations() { } @NotNull //这个方法需要注意,最终instance初始化和获取将在这里进行 public final KLazilyDCLSingleton getInstance() { //拿到代理对象 Lazy var1 = KLazilyDCLSingleton.instance$delegate; KProperty var3 = ?delegatedProperties[0]; //代理对象的getValue方法就是初始化instance和获取instance的入口。内部会判断instance是否被初始化过没有就会返回新创建的对象, //初始化过直接返回上一次初始化的对象。所以只有真正调用getInstance方法需要这个实例的时候instance才会被初始化。 return (KLazilyDCLSingleton)var1.getValue(); } private Companion() {//Companion构造器私有化 } // $FF: synthetic method public Companion(DefaultConstructorMarker $constructor_marker) { this(); } }
- Scrapy与 Selenium 的结合使用 Scrapy 是最流行的 Python 爬虫框架
deprecated相关搜索
-
daima
damain
dart
dataset
datasource
datediff
datediff函数
datepicker
datetime
db4o
dbi
dcloud
deallocate
debian安装
debugger
debugging
declaration
declarations
declare
decode函数