注解方式实现Spring IOC 和 DI
1. 注解概述
注释:给人看的提示信息
//
/*
/
/* */
注解:给程序看的提示信息
@XXX(xxx=xxx,xxx=xxx)
jdk5提供的新特性。可以用来实现轻量化配置。
2. sun提供的注解
@Override
告知编译器被标注的方法要重写父类中的方法,则编译器回去检查是否成功重写,如果没有成功重写会进行提示。
@Deprecated
标注方法为过时方法,则调用此方法时方法上会多出删除线,表示方法已经过时,不再推荐使用。
@SuppressWarnings
压制警告,告知编译器当前警告不再需要提示
3.自定义注解
a. 声明自定义注解
可以通过@Interface关键字来开发自定义注解,开发自定义注解的过程非常类似于开发一个接口。
b. 使用元注解来修饰自定义注解
所谓元注解是sun公司提供的专门用来修饰自定义注解的注解。
i. @Target
用来声明限定自定义注解可以使用的位置的元注解
其中可以通过配置ElementType来声明注解可以使用的位置,如果不配置默认可以用在任意位置。
ii. @Retention
用来声明自定义注解可以被保留到什么阶段。
默认情况下自定义的直接只能保留在源码阶段。
RetentionPolicy.SOURCE | Source级别,注解只保留在.java中,编译过后丢失 |
---|---|
RetentionPolicy.CLASS | Class级别,注解在.java和.class里存在,但在.class加载到内存中变为字节码时丢失。 |
RetentionPolicy.RUNTIME | Runtime级别,注解在.java .class 和 内存字节码中都存在,只有Runtime级别的注解可以在程序运行阶段通过反射进行操作。 |
iii. @Documented
控制自定义注解能否被文档提取工具提取到文档中
默认自定义注解是不会被javadoc文档提取工具提取到文档中的。
加上此注解就可以在生成文档时将自定义注解提取到文档。
iv. @Inherited
自定义注解是否具有继承性
默认没有,如果通过此注解标注,则自定义注解就具有了继承性。
c. 为自定义注解增加属性
为自定义注解声明属性的过程非常类似于为接口声明方法。
声明的属性必须是public的,不写默认就是public的。
注解的属性只能是八种基本数据类型、String类型、Class类型、枚举类型、其他注解类型及其以上类型的一维数组。
声明的属性需要在使用注解时进行赋值。
可以在声明注解属性时,通过default关键字为注解属性指定默认值。
如果注解属性时数组,但赋值时数组内只有一个值,则包裹数组的大括号可以省略。
如果注解的属性只有一个要赋值,且该属性的名称恰好是value,则赋值时value=可以省略
4.反射注解
只有RUNTIME级别的注解可以被反射。
在CLASS Field Method Constructor Package类上都有和反射注解相关的方法
<A extends Annotation .> | getAnnotation(Class annotationClass) 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 |
---|---|
Annotation[] | getAnnotations() 返回此元素上存在的所有注释。 |
boolean | isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。 |
5.注解的作用
注解是一种轻量化配置工具。
相对于配置文件
优点是减少了配置量,配置和代码在一起,代码在哪配置就在哪,方便与开发调试。
缺点是配置写死在了代码中,开发测试阶段无所谓,但一旦打成jar配置就无法再修改了,只能修改后重新打jar。
注解方式实现配置是配置文件方式进行配置的良好的改进,对于那些开发阶段的配置可以通过注解来简化开发,但核心的在开发完成打成jar后仍需要修改的配置还是要在配置文件中实现。
结合注解方式的配置 和 配置文件方式的配置可以结合两者的优点简化开发配置过程。
注解方式实现Spring IOC 和 DI的具体步骤
1. 注解方式实现IOC
a. 项目中导入包
文件已上传至
https://pan.baidu.com/s/1VQSalDJ3d6JVWqSc9vObPg
提取码:d0zg
b. 编写配置文件,额外导入context约束,并配置包扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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:component-scan base-package="cn.xxxx.domain"></context:component-scan>
</beans>
c. 在该包下的类如果想要被注册为bean,则通过@Component注解进行标注
package cn.xxxx.domain;
import org.springframework.stereotype.Component;
@Component
public class Person {
public void eat(){
System.out.println("人吃..");
}
}
d. 开发测试类,测试
package cn.xxxx.test;
import cn.xxxx.domain.Cat;
import cn.xxxx.domain.Dog;
import cn.xxxx.domain.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person p = (Person)context.getBean("person");
p.eat();
Dog dog = (Dog)context.getBean("dog");
dog.eat();
Cat cat = (Cat)context.getBean("cat");
cat.eat();
}
}
2. 自动id推断
看类名的第二个字母
如果第二个字母是小写,则类名首字母小写作为id
如果第二个字母是大写,则类名首字母不变作为id
也可以在@Compnent注解中通过value属性手工指定id,则不再自动推断而采用指定的id
3. 注解方式实现DI
a. 在applicationContext.xml中配置开启注解方式的DI
<context:annotation-config/>
b. 在bean中通过@Value注解实现属性的注入
i. 基本数据类型 String类型
public class Person{
@Value("zs")
private String name;
@Value("19")
private int age;
}
如果不想写死,也可以配置到外部Properties文件中,让Spring帮我们加载,之后通过${}语法进行引用
开发my.properties
name=ww
age=21
配置到Spring中
<!--加载配置文件-->
<context:property-placeholderlocation="my.properties"/>
在bean中引用
@Component
publi cclass Person{
@Value("${name}")
private String name;
@Value("${age}")
private inta ge;
}
ii. 集合类型 Map类型 Properties类型
在applicationContext.xml配置文件中引入util约束
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
">
配置数据
<!--设置集合数据-->
<util:list id="l1">
<value>v1</value>
<value>v2</value>
<value>v3</value>
</util:list>
<util:set id="s1">
<value>v1</value>
<value>v2</value>
<value>v3</value>
</util:set>
<util:map id="m1">
<entry key="k1" value="v1"></entry>
<entry key="k2" value="v2"></entry>
<entry key="k3" value="v3"></entry>
</util:map>
<util:properties id="p1">
<prop key="k1">v1</prop>
<prop key="k2">v2</prop>
<prop key="k3">v3</prop>
</util:properties>
通过@Value实现注入
@Component
public class Person{
@Value("${name}")
private String name;
@Value("${age}")
private int age;
@Value("#{@l1}")
private List<String>list;
@Value("#{@s1}")
private Set<String>set;
@Value("#{@m1}")
private Map<String,String>map;
@Value("#{@p1}")
private Propertiesprops;
}
iii. 自定义bean类型
使用@Autowired修饰属性,则会自动将自定义的bean进行注入
先按类型匹配,找当前属性类型(包括子孙类型)的bean,如果找到唯一的一个则直接注入,如果找不到或找到多个则按类型注入失败,开始按照id注入,寻找id和当前属性名一致的bean,如果找到就注入 如果找不到则按id注入也失败,抛出异常。
也可以同时配置@Autowired和@Qualifier,则此时直接按照@Qualifier指定的id进行bean的注入,如果找不到则直接抛出异常
4. 其他注解
a. @Scope(value=“singleton/prototype”)
配置当前bean为单例/多例。
默认为单例。
b. @Lazy
配置Bean的懒加载机制
c. @PostConstruct @PreDestroy
配置初始化和销毁方法
d. @Controller @Service @Repository @Component
以上四个注解功能一模一样,都是用来将类注解为Spring中的bean的。
但官方推荐在不同场合下用不同注解以示区别。
在web层使用@Controller
在service层使用@Service
在dao层使用@Repository
在三层之外用@Component
今天先聊到这里,我们下期见
------在下亦从文,弃武从文