Spring知识点总结之注解方式实现IOC和DI
Posted nanlinghan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring知识点总结之注解方式实现IOC和DI相关的知识,希望对你有一定的参考价值。
1. 注解概念
所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式。
关于注解的知识点,参看java基础课程中java基础加强部分的内容。
2. Spring中的注解
Spring除了默认的使用xml配置文件的方式实现配置之外,也支持使用注解方式实现配置,这种方式效率更高,配置信息清晰,修改更方便,推荐使用。
引入context名称空间:
在MyEclipse中导入spring-context-3.2.xsd约束文件,要求Spring来管理。
在applicationContext.xml文件中,引入该schema文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-3.2.xsd 9 "> 10 </beans>
**可以将以上头信息加入MyEclipse模版,方便后续自动生成。
3. 使用类注解
使用Spring的类注解可以通过注解注册类为bean,省去了配置文件中的<bean>配置。
a. 开启包扫描
在spring的配置文件中,开启包扫描,指定spring自动扫描哪些个包下的类。
<context:component-scan base-package="cn.tedu.beans"/>
案例:
<?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-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd "> <!-- 开启包扫描 --> <context:component-scan base-package="cn.tedu.beans"></context:component-scan> <!-- <bean id="person" class="cn.tedu.beans.Person"></bean> <bean id="cat" class="cn.tedu.beans.Cat"></bean> <bean id="dog" class="cn.tedu.beans.Dog"></bean> --> </beans>
b. 使用注解注册bean
这个包中的类会在spring容器启动时自动被扫描,检测是否需要自动配置为bean.
在配置的包中的类上使用@Component注解,则这个类会自动被注册为bean,使用当前类的class为<bean>的class,通常情况下使用类名首字母小写为<bean>id。
案例:
package cn.tedu.beans; import org.springframework.stereotype.Component; @Component public class Person{ }
c. bean的id
可以使bean类实现BeanNameAware接口,并实现其中的setBeanName方法,spring容器会在初始化bean时,调用此方法告知当前bean的id。通过这个方式可以获取bean的id信息。
通常情况下注解注册bean使用类名首字母小写为bean的id,但是如果类名的第二个字母为大写则首字母保留原样.
cn.tedu.beans.Person --> <bean id="person" class="cn.tedu.beans.Person"/>
cn.tedu.beans.NBA --> <bean id="NBA" class="cn.tedu.beans.NBA"/>
也可以通过在@Component中配置value属性,明确的指定当前类在注册到spring时bean的id
案例:
1 package cn.tedu.beans; 2 3 import org.springframework.beans.factory.BeanNameAware; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Qualifier; 6 import org.springframework.stereotype.Component; 7 8 @Component("per") 9 public class Person implements BeanNameAware{ 10 @Override 11 public void setBeanName(String name) { 12 System.out.println("==="+this.getClass().getName()+"==="+name); 13 } 14 }
4. 使用属性注解
使用属性注解,可以为bean配置属性的注入过程,省去了在配置文件中进行注入配置的过程,更加便捷。
a. 在配置文件中开启属性注解功能
<?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-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd "> <!-- 开启属性注解 --> <context:annotation-config></context:annotation-config> </beans>
b. 使用属性注解注入bean类型数据:
在bean中的属性上通过如下注解声明属性注入
@Autowired
也可以使用@Qualifier(value="dog1")注解,明确的指定,要注入哪个id的bean
代码:
package cn.tedu.beans; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; public class Person implements BeanNameAware{ @Autowired private Dog dog; @Autowired private Cat cat; public Dog getDog() { return dog; } public void setDogx(Dog dog) { this.dog = dog; } public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } @Override public String toString() { return "Person [dog=" + dog + ", cat=" + cat + "]"; } @Override public void setBeanName(String name) { System.out.println("=============="+this.getClass().getName()+"===="+name); } }
c. 属性注入bean类型数据的原理:
当spring容器解析xml时,发现开启了属性注解,则会在创建bean时,检测属性上是否存在@Autowired注解,如果发现该注解,则会通过当前属性的名称寻找是否存在该id的bean,如果存在则注入进来,如果不存在,再检查是否存在和当前属性类型相同的bean,如果由则注入进来,如果都没有则抛出异常.
**也可以使用@Resource(name="id")指定注入给定id的bean,但是这种方式不建议大家使用。
d. spring内置支持注入类型的注解方式的注入 - 非集合类型
spring中可以通过注解方式 注册bean,并可以通过@Autowired实现属性的自动注入,但注入的都是自定义的bean类型,如果类中包含例如 int long String等spring内置可注入的类型时,又该如何注入呢? 可以使用@Value注解来实现注入。
1 package cn.tedu.beans; 2 3 import org.springframework.beans.factory.BeanNameAware; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Value; 6 import org.springframework.stereotype.Component; 7 8 @Component("per") 9 public class Person implements BeanNameAware{ 10 @Value("999") 11 private int id; 12 13 @Value("zs") 14 private String name; 15 16 @Autowired 17 private Dog dog; 18 19 @Autowired 20 private Cat cat; 21 22 public Dog getDog() { 23 return dog; 24 } 25 public void setDogx(Dog dog) { 26 this.dog = dog; 27 } 28 public Cat getCat() { 29 return cat; 30 } 31 public void setCat(Cat cat) { 32 this.cat = cat; 33 } 34 35 @Override 36 public String toString() { 37 return "Person [id=" + id + ", name=" + name + ", dog=" + dog 38 + ", cat=" + cat + "]"; 39 } 40 @Override 41 public void setBeanName(String name) { 42 System.out.println("==="+this.getClass().getName()+"==="+name); 43 } 44 45 }
这种方式可以实现spring内置类型的注入,但是这种方式将注入的值写死在了代码中,后续如果希望改变注入的初始值,必须来修改源代码,此时可以将这些值配置到一个properties配置文件中,再在spring中进行引入。
e. spring内置支持注入类型的注解方式的注入 - 集合类型
需要将集合类型的数据配置到spring配置文件中,再通过@Value引入
配置过程:
将spring-util-3.2.xsd交给MyEclipse管理
在当前spring容器的配置文件中导入util名称空间
再通过适当的util标签注册数据
案例:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:util="http://www.springframework.org/schema/util" 5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/beans 8 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 9 http://www.springframework.org/schema/context 10 http://www.springframework.org/schema/context/spring-context-3.2.xsd 11 http://www.springframework.org/schema/util 12 http://www.springframework.org/schema/util/spring-util-3.2.xsd 13 "> 14 <!-- 开启属性注解 --> 15 <context:annotation-config></context:annotation-config> 16 <context:component-scan base-package="cn.tedu.beans"></context:component-scan> 17 <context:property-placeholder location="classpath:/person-data.properties"/> 18 19 <util:list id="l1"> 20 <value>北京</value> 21 <value>上海</value> 22 <value>广州</value> 23 <value>深证</value> 24 </util:list> 25 26 <util:set id="s1"> 27 <value>法师</value> 28 <value>射手</value> 29 <value>打野</value> 30 <value>战士</value> 31 <value>打野</value> 32 <value>坦克</value> 33 <value>打野</value> 34 </util:set> 35 36 <util:map id="m1"> 37 <entry key="k1" value="v1"></entry> 38 <entry key="k2" value="v2"></entry> 39 <entry key="k3" value="v3"></entry> 40 <entry key="k1" value="v4"></entry> 41 </util:map> 42 </beans> 43 44 再在类的属性中通过@Value注入赋值 45 package cn.tedu.beans; 46 47 import java.util.List; 48 import java.util.Map; 49 import java.util.Set; 50 51 import org.springframework.beans.factory.BeanNameAware; 52 import org.springframework.beans.factory.annotation.Autowired; 53 import org.springframework.beans.factory.annotation.Value; 54 import org.springframework.stereotype.Component; 55 56 @Component("per") 57 public class Person implements BeanNameAware{ 58 @Value("${id}") 59 private int id; 60 61 @Value("${name}") 62 private String name; 63 64 @Value("#{@l1}") 65 private List<String> addr; 66 67 @Value("#{@s1}") 68 private Set<String> jobs; 69 70 @Value("#{@m1}") 71 private Map<String,String> map; 72 73 @Autowired 74 private Dog dog; 75 76 @Autowired 77 private Cat cat; 78 79 public Dog getDog() { 80 return dog; 81 } 82 public void setDogx(Dog dog) { 83 this.dog = dog; 84 } 85 public Cat getCat() { 86 return cat; 87 } 88 public void setCat(Cat cat) { 89 this.cat = cat; 90 } 91 92 public void setBeanName(String name) { 93 System.out.println("=============="+this.getClass().getName()+"===="+name); 94 } 95 @Override 96 public String toString() { 97 return "Person [id=" + id + ", name=" + name + ", addr=" + addr 98 + ", jobs=" + jobs + ", map=" + map + ", dog=" + dog + ", cat=" 99 + cat + "]"; 100 } 101 } 102
5. 其他注解
a. @Scope(value="prototype")
配置修饰的类的bean是单例还是多例,如果不配置默认为单例
案例:
1 package cn.tedu.beans; 2 3 import org.springframework.context.annotation.Scope; 4 import org.springframework.stereotype.Component; 5 6 @Component 7 @Scope("prototype") 8 public class Dog { 9 10 }
b. @Lazy
配置修饰的类的bean采用懒加载机制
案例:
1 package cn.tedu.beans; 2 3 import org.springframework.context.annotation.Lazy; 4 import org.springframework.context.annotation.Scope; 5 import org.springframework.stereotype.Component; 6 7 @Component 8 @Lazy 9 public class Dog { 10 public Dog() { 11 System.out.println("Dog...被创建出来了..."); 12 } 13 }
c. @PostConstruct
在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执行。
d. @PreDestroy
在bean对应的类中 修饰某个方法 将该方法声明为销毁的方法,对象销毁之前调用的方法。
案例:
1 package cn.tedu.beans; 2 3 import javax.annotation.PostConstruct; 4 import javax.annotation.PreDestroy; 5 6 import org.springframework.stereotype.Component; 7 8 @Component 9 public class Dog { 10 public Dog() { 11 System.out.println("Dog...被创建出来了..."); 12 } 13 14 @PostConstruct 15 public void init(){ 16 System.out.println("Dog的初始化方法。。。"); 17 } 18 19 @PreDestroy 20 public void destory(){ 21 System.out.println("Dog的销毁方法。。。"); 22 } 23 }
e. @Controller @Service @Repository @Component
这四个注解的功能是完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。
其中@Component一般认为是通用的注解
而@Controller用在软件分层中的控制层,一般用在web层
而@Service用在软件分层中的业务访问层,一般用在service层
而@Repository用在软件分层中的数据访问层,一般用在dao层
以上是关于Spring知识点总结之注解方式实现IOC和DI的主要内容,如果未能解决你的问题,请参考以下文章