本文针对自动装载的一些注解进行描述。

基于注解的容器配置

@Required注解

@Required注解需要应用到Bean的属性的setter方法上面,如下面的例子:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
} // ... }

当Bean的属性配置了这个注解时,该Bean的属性必须在配置阶段就拥有明确的值,通过精确地Bean定义,或者通过自动装载。如果Bean的属性没有配置,容器会抛出异常。这一机制可以避免之后出现的空指针异常问题。当然,仍然推荐在Bean的类中使用断言,比如,在初始化方法中。这么做可以确保请求的引用或者值在容器外使用时是正确的。

@Autowired

JSR 330 的 @Inject注解在下面的例子中可以用来取代Spring的@Autowired注解。

开发者可以在构造函数上面使用@Autowired注解:

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
} // ... }

在Spring 4.3的版本中,@Autowired在构造函数上面的注解就已经不需要了,如果Bean定义了构造函数,会自动扫描直接DI的。如果配置了多个构造函数,则需要配置@Autowired来告诉容器使用哪一个来进行依赖注入。

当然,@Autowired可以注入到传统的setter方法上面:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
} // ... }

开发者也可以将这个注解运用到任何名字任何参数的方法上面:

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
} // ... }

开发者也可以将@Autowired用到域上面,甚至和构造函数混用:

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
private MovieCatalog movieCatalog; @Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
} // ... }

当然,也可以根据类型,将所有的ApplicationContext中的类型的Bean进行依赖注入,可以通过注解将多个Bean注入到Array类型中。

public class MovieRecommender {

    @Autowired
private MovieCatalog[] movieCatalogs; // ... }

也可以注入到集合类型之中:

public class MovieRecommender {

    private Set<MovieCatalog> movieCatalogs;

    @Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
} // ... }

开发者所定义的Bean可以通过实现org.springframework.core.Ordered接口或者通过使用@Order或者标准的@Priority注解来确定注入到array或者list中的顺序。

Map类型也可以注入进去,只要key的类型为String就可以注入进去。Map的值可以是任何一种容器中的Bean的类型,key当然就是对应Bean的名字。

public class MovieRecommender {

    private Map<String, MovieCatalog> movieCatalogs;

    @Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
} // ... }

默认的话,自动装载会在没有候选Bean可用时失败,默认的行为就是将带有注解的方法,构造函数,以及实例变量作为必须的依赖。当然,这个默认的行为可以被改为如下代码:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired(required=false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
} // ... }

每个类仅有一个注解构造函数可以被标记为必须的,但是非必须的够早函数可以注解多个。在存在多个非必须注解(required=false)的情况下,Spring会选择一个最贪婪的构造函数(满足最多的依赖的)。

@Autowired注解要优于@Required注解。required属性来表明其属性是否为必须的,而当依赖不能被注入的话,就会被忽略掉。而@Required朱姐,是比@Autowired要强的,它会要求依赖必须注入。如果没有对应的依赖进行注入,就会抛出异常。

开发者可以使用@Autowired来自动装载一些依赖:BeanFactory, ApplicationContext, Environment, ResourceLoader,ApplicationEventPublisher以及MessageSource等。这些接口以及其扩展接口,比如ConfigurableApplicationContext或者ResourcePatternResolver都可以解析,不用特殊配置。

public class MovieRecommender {

    @Autowired
private ApplicationContext context; public MovieRecommender() {
} // ... }

@Autowired,@Inject,@Resource以及@Value等注解都是通过Spring的BeanPostProcessor的实现来实现自动装载的,也就意味着开发者不能够通过自己的BeanPostProcessor或者BeanFactoryPostProcessor来应用这些注解。开发者自己的类型必须通过明确的XML或者Spring@Bean方法来定义。

通过@Primary来自动装载

由于通过类型来装载可能导致多个候选者,通常很有必要来控制选择依赖的过程,一种方式就是通过Spring的@Primary注解。@Primary注解表明当一个Bean需要进行依赖注入的时候,如果有多个候选者可能注入到单值的依赖之中,那么该Bean拥有优先权。如果只有一个primary的Bean的话,那么这个Bean将成为自动装载的依赖。

参考如下代码:

@Configuration
public class MovieConfiguration { @Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... } @Bean
public MovieCatalog secondMovieCatalog() { ... } // ... }

上面的代码中,firstMovieCatalog作为主要的MovieCatalog

当使用了上面的配置后,下面的Bean在自动装载的时候,会装载firstMovieCatalog

public class MovieRecommender {

    @Autowired
private MovieCatalog movieCatalog; // ... }

如果使用XML来进行定义的话,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <bean class="example.SimpleMovieCatalog" primary="true">
<!-- inject any dependencies required by this bean -->
</bean> <bean class="example.SimpleMovieCatalog">
<!-- inject any dependencies required by this bean -->
</bean> <bean id="movieRecommender" class="example.MovieRecommender"/> </beans>

通过限定符的自动装载

@Primary在相同类型的几个实例之间选择选择依赖的时候,是一种很高效的方式。但是如果想要更多的控制自动装载的过程,@Qualifier注解就更为有用了。开发者可以通过将趣分期的值和参数来关联起来,以缩小类型匹配的范围,这样就能够自动装配到特值得Bean了。代码如下:

public class MovieRecommender {

    @Autowired
@Qualifier("main")
private MovieCatalog movieCatalog; // ... }

@Qualifier注解可以指定到构造函数的参数,或者是方法上面:

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
public void prepare(@Qualifier("main")MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
} // ... }

而依赖的Bean的在XMl的定义,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <bean class="example.SimpleMovieCatalog">
<qualifier value="main"/> <!-- inject any dependencies required by this bean -->
</bean> <bean class="example.SimpleMovieCatalog">
<qualifier value="action"/> <!-- inject any dependencies required by this bean -->
</bean> <bean id="movieRecommender" class="example.MovieRecommender"/> </beans>

在匹配中,Bean的名字就相当于默认的限定符的值。这样,开发者可以定义一个Bean的id为main而不使用限定符元素,也会有一样的匹配结果的。然而,尽管开发者可以通过这个便利来通过名字引用指定的Bean,@Autowired在根本上仍然是通过类型来进行依赖注入的,只不过有着可选的限定符。这也意味着限定符的值,甚至Bean的名字,总是能缩小值匹配的集合,但是并不能明确的如Bean的id一样指向一个唯一的Bean。好的限定符的值比如main或者EMEA或者persistent,所表示的是特定的组件,跟Bean的id是相互独立的。Bean的id,在前面匿名Bean中是会自动生成的。

限定符也能够应用到集合类型的,如前面的例子中,Set<MovieCatalog>。在这种情况下,所有根据声明的趣分期的匹配的Bean都会被注入到集合之中。这也说明趣分期并不是唯一的,限定符更类似一种过滤标准。比如:开发者可以定义多个MovieCatalogBean而且配置其相同的限定符的值,比如说action,那么所有含有@Qualifier("action")的Bean都会注入到Set<MovieCatalog>之中。

如果开发者希望通过名字来进行依赖注入,甚至仅仅使用@Qualifier的值进行注入,那么可以不用@Autowired而是使用JSR-250@Resource注解,这个注解是通过名字来进行依赖注入的,而与类型无关。

对于本身定义为集合类型或者数组类型的Bean来说,@Resource是个很好的解决方案,可以通过名字来引用特定的集合或者数组元素。当然,在Spring4.3的版本中,集合类型,map以及数组类型也能通过Spring的@Autowired的类型匹配算法匹配到了。

@Autowired可以用在实例变量,构造函数,或者多参数的方法上,允许通过限定符注解来缩小匹配范围。相比之下,@Resource仅仅在实例变量和Setter方法的情况下支持依赖注入。因此,如果需要在多参数的方法或者构造函数上约束注入的依赖,需要使用限定符而不要用@Resource

开发者也可以定义自己的限定符注解,代码如下:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre { String value();
}

之后就可以将自定义的限定符应用到自动装载的参数上面了,如下:

public class MovieRecommender {

    @Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog; @Autowired
public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
} // ... }

下一步,需要给候选的Bean提供限定符信息。开发者可以通过在<bean/>的子标签<qualifier/>标签中来指定type的值来匹配自定义的限定符注解。匹配类型注解是完整的类名的,需要和自定义的类名一致。或者,如果没有命名冲突的话,可以仅仅使用类名。参考XML代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean> <bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean> <bean id="movieRecommender" class="example.MovieRecommender"/> </beans>

在很多情况下,仅仅使用注解就足够了。而且这一点在注解服务更为泛化的情况下更为有用。比如说,开发者需要提供一个线下的目录的话,可以参考如下的定义:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline { }

之后的使用不要指定值了,自动装载配置如下:

public class MovieRecommender {

    @Autowired
@Offline
private MovieCatalog offlineCatalog; // ... }

XML中的配置也较为简单,如下:

<bean class="example.SimpleMovieCatalog">
<qualifier type="Offline"/>
<!-- inject any dependencies required by this bean -->
</bean>

当然,开发者也可以在一个value属性不足的情况下定义更多的限定符的参数来限定Bean的自动装载。如果在自定义的限定符注解中定义了多个限定的参数,那么Bean必须符合全部的参数才能被视为自动装载的候选者。参考如下的例子:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier { String genre(); Format format(); }

其中Format是一个枚举类型。

public enum Format {
VHS, DVD, BLURAY
}

在前面自定义的限定符中,则必须满足两个属性的匹配才能够进行依赖注入:

public class MovieRecommender {

    @Autowired
@MovieQualifier(format=Format.VHS, genre="Action")
private MovieCatalog actionVhsCatalog; @Autowired
@MovieQualifier(format=Format.VHS, genre="Comedy")
private MovieCatalog comedyVhsCatalog; @Autowired
@MovieQualifier(format=Format.DVD, genre="Action")
private MovieCatalog actionDvdCatalog; @Autowired
@MovieQualifier(format=Format.BLURAY, genre="Comedy")
private MovieCatalog comedyBluRayCatalog; // ... }

XML中Bean的定义如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Action"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean> <bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Comedy"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean> <bean class="example.SimpleMovieCatalog">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean> <bean class="example.SimpleMovieCatalog">
<meta key="format" value="BLURAY"/>
<meta key="genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean> </beans>

可以看出,限定符的定义是类似key-value的形式存在于<qualifier/>的子标签中的。除此之外,如果限定符有效,则优先选择匹配的Bean作为依赖进行注入,如果没有,自动装载的机制会在不存在限定符的时候自动退回到<meat/>,如上述代码的最后两个Bean。

使用泛型作为自动装载的限定符

关于@Qualifier注解,也可以使用Java泛型来作为限定符。比如说,有如下配置:

@Configuration
public class MyConfiguration { @Bean
public StringStore stringStore() {
return new StringStore();
} @Bean
public IntegerStore integerStore() {
return new IntegerStore();
} }

假设上面提到的Bean实现了一个泛型接口比如说:Store<String>Store<Integer>,开发者可以使用@Autowire来自动装载,而泛型的类型则作为限定符,参考如下代码:

@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean @Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean

泛型的限定同样可以用于List,Map或者Array上面,如下:

// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@Autowired
private List<Store<Integer>> s;

CustomAutowireConfigurer

CustomAutowireConfigurer是一个BeanFactoryPostProcessor,这个后置处理器可以注册开发者自己的限定符注解,让开发者的注解不依赖于Spring限定符注解。

<bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>

AutowireCandidateResolver通过以下的几种方式来决定自动装载的候选Bean:

  • Bean定义中的autowire-candidate的值
  • 任何<beans/>标签中定义的default-autowire-candidates的值
  • @Qualifier注解和任何在CustomAutowireConfigurer中定义的自定义的限定符注解

当多个Bean限定为自动装载的候选时, 前文中提到的primary属性是优先考虑的。

@Resource注解

Spring支持JSR-250标准中的@Resource注解来注入实例变量或者setter方法。这也是Java EE 5和6之中的常见模式,举例来说,在JSF 1.2中管理的Bean或者是JAX-WS 2.0 endpoint等。Spring也支持这种模式来注入Spring管理的对象。

@Resource需要一个名字的属性,而默认的情况下,Spring会将Bean的名字注入。换言之,@Resource的自动装载是基于名字语义的,就如同如下的例子一样:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
} }

如果没有明确指定名字的话,默认的名字就是实例变量的变量名,或者Setter方法中解析出来的名字。以实例变量为例,就取变量的名字作为默认的名字,如果是Setter的方法的话,会取Bean属性的名字。所以,如下的例子会注入Bean的名字的movieFinder的Bean实例。

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
} }

注解解析的名字是通过ApplicationContext来解析的。如果开发者配置了明确的Spring SimpleJndiBeanFactory的话,这些名字可以通过JNDI来解析。然而,Spring团队仍然建议开发者依赖其默认的行为并简单实用Spring的JNDI查找能力。

在使用@Resource而没有明确指定名字的情况,它比较类似@Autowired注解,@Resource会优先查找类型匹配而不是名字匹配,也能够解析一些常见的依赖:BeanFactory,ApplicationContext,ResourceLoader,ApplicationEventPublisher以及MessageSource等接口。

在如下的例子中,customerPreferenceDao实例变量会优先查找名字为customerPreferenceDao的Bean来进行依赖注入,然后在进行类型匹配CustomerPreferenceDaocontext实例变量作为常见的实例会自动通过ApplicationContext注入进去。

public class MovieRecommender {

    @Resource
private CustomerPreferenceDao customerPreferenceDao; @Resource
private ApplicationContext context; public MovieRecommender() {
} // ... }

@PostConstructPreDestroy注解

CommonAnnotationBeanPostProcessor不仅仅识别@Resource注解,也识别JSR-250标准中的生命周期注解。在Spring核心技术IoC容器(六)中针对回调函数的描述了注解外其他的方法实现回调。CommonAnnotationBeanPostProcessor是注册在Spring的ApplicationContext之中的,它提供了一些方法来关联Spring的声明周期来进行回调,在下面的例子中,缓存会在构造后和销毁前进行回调。

public class CachingMovieLister {

    @PostConstruct
public void populateMovieCache() {
// populates the movie cache upon initialization...
} @PreDestroy
public void clearMovieCache() {
// clears the movie cache upon destruction...
} }

关于Spring的生命周期的机制在前文 《Spring核心技术IoC容器(六)》之中有更详细的描述。

Spring核心技术(八)——Spring自动装载的注解的更多相关文章

  1. 玩转spring MVC(八)----spring MVC整合json

    这篇文章在前边项目的基础上来整合json,最新项目资料见:http://download.csdn.net/detail/u012116457/8436187 首先需要的jar包:jackson-co ...

  2. Spring框架(三) JDBCTemplate,声明式事务,自动装载(注解)

    JDBCTemplate 按照标准正常项目的结构 结构图: model层 dao层 实现  dao:(DateBase Access Object) 数据访问对象,dao层只用来访问数据库和模型层 s ...

  3. Spring第八篇【XML、注解实现事务控制】

    前言 本博文主要讲解Spring的事务控制,如何使用Spring来对程序进行事务控制-. 一般地,我们事务控制都是在service层做的..为什么是在service层而不是在dao层呢??有没有这样的 ...

  4. Spring第八发—自动装配及让Spring自动扫描和管理Bean

    依赖注入–自动装配依赖对象(了解即可) 对于自动装配,大家了解一下就可以了,实在不推荐大家使用.例子: byName:按名称装配,可以根据属性的名称,在容器中寻找跟该属性名相同的bean,如果没有找到 ...

  5. Spring入门(八):自动装配的歧义性

    1. 什么是自动装配的歧义性? 在Spring中,装配bean有以下3种方式: 自动装配 Java配置 xml配置 在这3种方式中,自动装配为我们带来了很大的便利,大大的降低了我们需要手动装配bean ...

  6. Spring核心技术(十)——JSR-330标准注解

    从Spring 3.0开始,Spring开始支持JSR-330标准的注解(依赖注入).这些注解和Spring注解扫描的方式是一直的,开发者只需要在classpath中配置相关的jar包即可. 如果开发 ...

  7. Spring学习(八)-----Spring注入值到集合类型的例子

    下面例子向您展示Spring如何注入值到集合类型(List, Set, Map, and Properties). 支持4个主要的集合类型: List – <list/> Set – &l ...

  8. spring入门(八) spring mvc设置默认首页

    1.web.xml配置如下 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3// ...

  9. Spring核心技术(九)——Spring管理的组件和Classpath扫描

    Spring管理的组件和Classpath的扫描 在前文描述中使用到的Spring中的Bean的定义,都是通过指定的XML来配置的.而前文中描述的注解的解析则是在源代码级别来提供配置元数据的.在那些例 ...

随机推荐

  1. Python——nose实例示例

    1. 脚本示例: 执行结果: 2. 脚本示例: 执行结果: 由以上截图可以看出执行顺序: 大体可以得出如下结论: 1)测试的顺序总体上按照包—>模块—>类的顺序进行: 2) 然后按照测试用 ...

  2. [hdu4089] Activation【概率dp 数学期望】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4089 本来可以一遍过的,结果mle了一发...注意要用滚动数组. 令f(i, j)表示队列剩余i个人,这 ...

  3. Latex新人教程

    1.LaTeX软件的安装和使用 方法A(自助):在MikTeX的官网下载免费的MikTeX编译包并安装.下载WinEdt(收费)或TexMaker(免费)等编辑界面软件并安装. 方法B(打包):在ct ...

  4. [完美方案+无懈可击]ubuntu 14.04(LTS) + GTX 980Ti显卡配置

    安装好系统之后出现的问题: 1 不能上网:后来通过删除链接新建一个以太网链接(自动DHCP)重启莫名其妙就好使了. 2 分辨率只有两个:1024x ? 和 800x600. 分辨率低到让人头痛.通过查 ...

  5. laravel5.5文件上传

    /**     * 上传文件     * @param Request $request     * @return array     */    public function upload(Re ...

  6. 在Bootstrap中得模态框(modal)中下拉不能显示得问题

    $.fn.modal.Constructor.prototype.enforceFocus = function () { $("#insertModal").on("s ...

  7. 内存管理总结-autoreleasePool

    转自其他 序言 无论是在MRC时期还是ARC时期,做过开发的程序员都接触过autoreleasepool.尽管接触过但本人对它还不是很了解.本文只是将自己的理解说出来.在内存管理的文章中提到了OC的内 ...

  8. vue-cropper

    项目中用到了vue-cropper插件,让我觉得很好用附上两个地址 vue-cropper在git上的地址 https://github.com/xyxiao001/vue-cropper 针对vue ...

  9. 【4412开发板使用经验分享】迅为4412开发板I2C驱动问题

    本文转自迅为论坛:bbs.topeetboard.com 我想写DS3231 的驱动 但是读回的数据老是-6 硬件: 我I2C设备连接的这几个GPIO,看了2.5的手册,接口应该是链接正确的 软件 分 ...

  10. JAVA——不简单的fianl关键字

    protected用来修饰 域,代表域的访问权限是:包权限 或者 不同包,但是是子类 : final 修饰常量只要是该常量代入的计算式,在编译时期,就会被执行计算,以减轻运行时的负担.(只对基本数据类 ...