Spring注解方式实现IOC和DI
-
Spring注解
Spring除了默认的使用xml配置文件的方式实现配置之外,也支持使用注解方式实现配置,这种方式效率更高,配置信息清晰,代码在哪对应的配置就在哪,方便开发阶段修改,推荐使用。
所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式。
关于注解的知识点,参看java基础课程中java基础加强部分的内容。 -
Spring注解方式实现IOC
a.导入开发包

b.编写配置文件
<?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
">
</beans>
**可以将以上头信息加入MyEclipse模版,方便后续自动生成。
c.开启包扫描
在配置文件中,开启包扫描,指定spring自动扫描哪些个包下的类。只有在指定的扫描包下的类上的IOC注解才会生效。
<?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>
d.使用注释注册bean
在配置的包中的类上使用 @Component注解,则这个类会自动被注册为bean,使用当前类的class为< bean>的class,通常情况下使用类名首字母小写为< bean>id。
案例:
package cn.tedu.beans;
import org.springframework.stereotype.Component;
@Component
public class Person{
}
e.bean的id
通常情况下注解注册bean使用类名首字母小写为bean的id,但是如果类名的第二个字母为大写则首字母保留原样.
cn.tedu.beans.Person --> <bean id="person" class="cn.tedu.beans.Person"/>
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属性,明确的指定bean的id
案例:
**可以使bean类实现BeanNameAware接口,并实现其中的setBeanName方法,spring容器会在初始化bean时,调用此方法告知当前bean的id。通过这个方式可以获取bean的id信息。
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;
@Component("per")
public class Person implements BeanNameAware{
@Override
public void setBeanName(String name) { System.out.println("==="+this.getClass().getName()+"==="+name);
}
}
- Spring注解方式实现IOC - 工厂注册bean
Spring默认通过反射创建bean,如果某些bean没有无参构造器或创建过程非常复杂,则无法通过简单的反射创建bean,此时可以通过指定创建bean的工厂,令SpringIOC通过工厂来创建bean,从而进行注册。
可以通过配置文件方式配置bean工厂,同样也可以通过注解配置bean工厂。
a.配置工厂类
工厂类必须放在包扫描目录下,且被@Component注解修饰
b.配置工厂类中生产bean的方法
工厂中生产bean的方法要被@Bean修饰
则此方法会被SpringIOC调用,并将返回的对象注册为Spring的bean,默认自动推断id,也可以通过value属性手工指定id。
@Component
public class Pesron5Factory {
@Bean("per5")
public Person5 getInstance(){
return new Person5("xx");
}
}
- Spring注解方式实现DI
a.导入开发包

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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
">
</beans>
c.配置开启注解实现DI选项
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
">
<!-- 开启IOC包扫描 -->
<context:component-scan base-package="cn.tedu.domain"/>
<!-- 开启注解配置DI -->
<context:annotation-config></context:annotation-config>
</beans>
d.注解方式注入spring内置支持的类型数据 - 非集合类型
spring中可以通过 @Value注解来实现spring内置支持的类型的属性的注入。
package cn.tedu.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
@Value("zs")
private String name;
@Value("19")
private int age;
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
这种方式可以实现spring内置支持类型的注入,但是这种方式将注入的值写死在了代码中,后续如果希望改变注入的值,必须来修改源代码,此时可以将这些值配置到一个properties配置文件中,再在spring中进行引入。



e.注解方式注入spring内置支持的类型数据 - 集合类型
引入util名称空间,通过适当的util标签注册数据
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
">
<!-- 开启IOC包扫描 -->
<context:component-scan base-package="cn.tedu.domain"/>
<!-- 开启注解配置DI -->
<context:annotation-config></context:annotation-config>
<!-- 引入Properties文件 -->
<context:property-placeholder location="classpath:/stu.properties"/>
<!-- 配置集合数据 -->
<util:list id="l1">
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</util:list>
<util:set id="s1">
<value>111</value>
<value>222</value>
<value>333</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="p1">v1</prop>
<prop key="p2">v2</prop>
<prop key="p3">v3</prop>
</util:properties>
</beans>
再在类的属性中通过@Value注入赋值
package cn.tedu.domain;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
@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 Properties prop;
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", list=" + list
+ ", set=" + set + ", map=" + map + ", prop=" + prop + "]";
}
}
f.使用注解注入自定义bean类型数据:
在bean中的属性上通过@Autowired实现自定义bean类型的属性注入
代码:
package cn.tedu.domain;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
@Autowired
private Dog dog;
@Autowired
private Cat cat;
@Override
public String toString() {
return "Student [dog="+ dog + ", cat=" + cat + "]";
}
}
当Spring容器解析到@Component注解时,创建当前类的bean在spring容器中进行管理,在创建bean的过程中发现了@Autowired注解,会根据当前bean类型,寻找在spring中是否存在该类型的bean,找到直接注入,如果找不到还会检查是否有子孙类、实现类存在,如果存在唯一的则自动注入,如果还是没有找到或找到多个无法注入,则还会按照属性名对应id去查找对应的bean,如果存在则注入,如果还是没有找到则抛出异常。
也可以额外配置@Qualifier(value=“dog1”)注解强制要求按照id寻找bean,则此时会直接使用给定的id寻找bean,而不会进行基于类型的匹配。

**也可以使用@Resource(name=“id”)指定注入给定id的bean,但是这种方式不建议大家使用。
- 其他注解
a.@Scope(value=“prototype”)
配置修饰的类的bean是单例还是多例,如果不配置默认为单例
案例:
package cn.tedu.domain;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class Teacher {
}
b.@Lazy
配置修饰的类的bean采用懒加载机制
案例:
package cn.tedu.domain;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
@Lazy
public class Teacher {
public Teacher() {
System.out.println("teacher construct..");
}
}
c.@PostConstruct
在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执行。
d.@PreDestroy
在bean对应的类中 修饰某个方法 将该方法声明为销毁的方法,对象销毁之前调用的方法。
案例:
package cn.tedu.beans;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class Dog {
public Dog() {
System.out.println("Dog...被创建出来了...");
}
@PostConstruct
public void init(){
System.out.println("Dog的初始化方法。。。");
}
@PreDestroy
public void destory(){
System.out.println("Dog的销毁方法。。。");
}
}
e.@Controller @Service @Repository @Component
这四个注解的功能是完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。
其中@Component一般认为是通用的注解
而@Controller用在软件分层中的控制层,一般用在web层
而@Service用在软件分层中的业务访问层,一般用在service层
而@Repository用在软件分层中的数据访问层,一般用在dao层
本文详细介绍了Spring框架如何通过注解实现IoC(控制反转)和DI(依赖注入)。首先,讲解了如何配置Spring以启用注解扫描,然后展示了如何使用@Component注解注册bean,并自动推断bean的id。接着,介绍了通过@Bean注解配置工厂方法创建bean。对于DI,文章涵盖了使用@Value注入基本类型和集合,以及如何通过@Autowired实现自定义bean类型的注入。此外,还提到了其他注解如@Scope、@Lazy、@PostConstruct和@PreDestroy,以及@Controller、@Service、@Repository和@Component等组件注解的用途。最后,讨论了如何通过@Qualifier指定注入的bean。
651

被折叠的 条评论
为什么被折叠?



