一、常用注解:@Autowired注解、@Component注解
不使用任何注解(与后面使用注解的比对):pojo类和配置文件applicationContext.xml
package com.pojo;
public class Student {
private Teacher teacher;
private Course course;
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public void setCourse(Course course) {
this.course = course;
}
@Override
public String toString() {
return super.toString() + " - " + teacher + " - " + course;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="student" class="com.pojo.Student">
<property name="teacher" ref="teacher"></property>
<property name="course" ref="course"></property>
</bean>
<bean id="teacher" class="com.pojo.Teacher"></bean>
<bean id="course" class="com.pojo.Course"></bean>
</beans>
main函数
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.pojo.Student;
public class TestSpring {
public static void main(String[] args) {
//访问applciationContext.xml
//ApplciatinoContext是Spring中的一个接口,它有两个实现类ClassPathXmlApplicationContext和FileSystemXmlApplicationContext
//Java中一般使用ClassPathXmlApplicationContext类创建Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" });
Student student = (Student) context.getBean("student");
System.out.println(student);
}
}
输出:
com.pojo.Student@6f1fba17 - com.pojo.Teacher@185d8b6 - com.pojo.Course@67784306
1、关于@Autowired注解
@Autowired可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
(1)@Autowired对类成员变量标注
@Autowired对类成员变量标注,则该类成员变量不在需要setter(设值注入).配置文件applicationContext.xml中可以移除Student类的引用类成员变量的<property.../>标签:
package com.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class Student {
@Autowired
private Teacher teacher;
@Autowired
private Course course;
@Override
public String toString() {
return super.toString() + " - " + teacher + " - " + course;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="student" class="com.pojo.Student">
</bean>
<bean id="teacher" class="com.pojo.Teacher"></bean>
<bean id="course" class="com.pojo.Course"></bean>
</beans>
输出:
com.pojo.Student@6f1fba17 - com.pojo.Teacher@185d8b6 - com.pojo.Course@67784306
对于pojo中的类,对其中的类成员变量使用@Autowired标注后,不需再为其提供setter-getter方法,因为可以自动装配。
配置文件applicationContext.xml中的如何配置,移除Student类的引用类成员变量的<property.../>标签,加上<context:annotation-config/> 表示告诉Spring要用注解的方式进行配置。
关于<context:annotationconfig/>:
<context:annotationconfig/> 将隐式地向 Spring 容器注册
AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
、PersistenceAnnotationBeanPostProcessor
以及equiredAnnotationBeanPostProcessor
这 4 个 BeanPostProcessor。表示告诉Spring要用注解的方式进行配置。
(2)@Autowired对setter方法标注(设值注入)
上面讲到,如果使用@Autowired标注到类成员变量上,就不需要setter,因为可以自动装配。其实将@Autowired注解放到setter上面,和将@Autowired标注到类成员变量上效果是一样的,都是自动装配。
package com.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class Student {
private Teacher teacher;
private Course course;
@Autowired
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Autowired
public void setCourse(Course course) {
this.course = course;
}
@Override
public String toString() {
return super.toString() + " - " + teacher + " - " + course;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="student" class="com.pojo.Student">
</bean>
<bean id="teacher" class="com.pojo.Teacher"></bean>
<bean id="course" class="com.pojo.Course"></bean>
</beans>
输出:
com.pojo.Student@6f1fba17 - com.pojo.Teacher@185d8b6 - com.pojo.Course@67784306
故,将@Autowired注解放到setter上面,和将@Autowired标注到类成员变量上效果是一样的,都是自动装配。
(3)@Autowired对构造函数标注(构造注入)
如果将@Autowired标注到构造函数上会怎样呢?如果是无参构造函数,标注它没有任何意义,因为起不到设置value的效果,所以使用@Autowired标注的构造函数都是带参构造函数,使用构造注入设置value。
package com.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class Student {
private Teacher teacher;
private Course course;
@Autowired
public Student(Teacher teacher, Course course) {
this.teacher = teacher;
this.course = course;
}
@Override
public String toString() {
return super.toString() + " - " + teacher + " - " + course;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="student" class="com.pojo.Student">
</bean>
<bean id="teacher" class="com.pojo.Teacher"></bean>
<bean id="course" class="com.pojo.Course"></bean>
</beans>
输出:
com.pojo.Student@6f1fba17 - com.pojo.Teacher@185d8b6 - com.pojo.Course@67784306
故,将@Autowired注解放到构造函数上面,和将@Autowired标注到类成员变量上效果是一样的,都是自动装配。
附:如果配置文件applicationContext.xml中0个<bean../>或两个<bean../>和pojo对应的Bean都会报错。且看下面:
(1)applicationContext.xml中0个<bean../>和pojo的Bean类对应。
错误:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException
解决方法:只有一个,就是applicationContext.xml文件中将<bean../>加上去。(注意,关于 使用@Autowired(required = false)这样的方式,使用自动注入又允许不注入,仅仅是开发或测试时使用,我认为不算一种根本上的解决方案,根本上的解决方案还是要在配置文件applicationContext.xml中添加相应的<bean../>)
(2)applicationContext.xml中2个<bean../>和pojo的Bean类对应。
出现BeanCreationException
异常,这种异常仅在低版本的Spring中出现,解决方式是添加@Qualifier("xxx")指定注入bean的名称,在高版本的Spring中不会出现这个异常,略过。
2、关于@Component注解
虽然我们可以通过 @Autowired
或 @Resource
在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过@Autowired
或 @Resource
为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。能否也通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置呢?答案是肯定的,我们通过 Spring 2.5 提供的@Component
注释就可以达到这个目标了。
@Component 仅需要在类定义处,使用@Component注释就可以将一个类实例化为 Spring 容器中的 Bean,相当于配置文件中的<bean id="" class=""/>
2.1 使用@Component注解——Student不引用类成员变量:
package com.pojo;
import org.springframework.stereotype.Component;
@Component("student")
public class Student {
private int age = 20;
private String name = "小明";
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return super.toString() + " - " + age + " - " + name;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.pojo"/>
</beans>
输出:
com.pojo.Student@30b8a058 - 20 - 小明
故,@Component注解实现了将applicationContext.xml中的<bean../>去掉的原理。
2.2 使用@Component注解——Student引用类成员变量teacher和course:
(因为main函数中要把结果打印出来,而使用@Component时将配置文件applicaitonContext.xml中的所有<bean.../>全部删去了,无法设置Student对Teacher和Course的引用,所以要引用类成员变量,使用@Component的时候一定要使用@Autowired)
package com.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("student")
public class Student {
@Autowired
private Teacher teacher;
@Autowired
private Course course;
@Override
public String toString() {
return super.toString() + " - " + teacher + " - " + course;
}
}
package com.pojo;
import org.springframework.stereotype.Component;
@Component
public class Course {
}
package com.pojo;
import org.springframework.stereotype.Component;
@Component
public class Teacher {
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.pojo"/>
</beans>
输出:
com.pojo.Student@5d76b067 - com.pojo.Teacher@2a17b7b6 - com.pojo.Course@4f063c0a
和第一个不使用任何注解是一样的,效果实现。故,@Component注解实现了将applicationContext.xml中的<bean../>去掉的原理。
附加一点:关于 <context:annotation-config/>和<context:component-scan/>。
<context:component-scan/> 配置项不但启用了对类包进行扫描以实施注释驱动 Bean 定义的功能,同时还启用了注释驱动自动注入的功能(即还隐式地在内部注册了
AutowiredAnnotationBeanPostProcessor
和CommonAnnotationBeanPostProcessor
),因此当使用 <context:component-scan/> 后,就可以将 <context:annotation-config/> 移除了。就像上面代码中表现的那样,去掉了<context:annotation-config/> ,只留下<context:component-scan base-package="xxx.xxx"/>就够了
3、关于@Repository注解
@Repository注解只能标注在Dao层,用于将数据访问层 (DAO层) 的类标识为 Spring Bean。具体只需将该注解标注在 DAO类上即可。如:
public class StudentDaoImpl implements StudentDao {
}
@Repository的作用不只是将类识别为 Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。 Spring 本身提供了一个丰富的并且是与具体的数据访问技术无关的数据访问异常结构,用于封装不同的持久层框架抛出的异常,使得异常独立于底层的框架。
4、关于@Service注解
@Service 通常作用在业务层,@Service是@Component注解的特殊形式(即在服务层的形式),它的功能与@Component注解一样(即从xml配置文件中移除Service服务定义配置),即使将它改为@Component注解也没有关系。项目开发中,我们之所以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图,告诉其他同事或后继维护人员这是一个Service服务,这是Service服务层。
5、关于@Controller注解
@Constroller 通常作用在控制层,但是目前该功能与 @Component 相同(即从xml配置文件中移除Service服务定义配置)即使将它改为@Component注解也没有关系。项目开发中,我们之所以在服务层类中使用 @Controller而不是 @Component,因为它以更好的方式指定了意图,告诉其他同事或后继维护人员这是一个控制器,这是Controller控制层。
此外,@Controller注解是SpringMVC的注解,Spring和SpringMVC互为父子容器,Spring是父容器,父容器无法访问到子容器的注解,所以无法演示。
二、不常用注解:@Resource注解、@PostConstruct注解和@PreDestory注解
1、关于@Resource注解
@Resource
的作用相当于 @Autowired
,只不过 @Autowired
按 byType 自动注入,而@Resource
默认按 byName 自动注入罢了。@Resource
有两个属性是比较重要的,分别是 name 和 type,Spring 将@Resource
注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
@Resource注解对类成员变量或setter方法进行标注,完成自动装配的工作。
@Resource注解对类成员变量标注:
package com.pojo;
import javax.annotation.Resource;
public class Student {
@Resource
private Course course;
@Resource
private Teacher teacher;
@Override
public String toString() {
return super.toString() + " - " + course + " - " + teacher;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="student" class="com.pojo.Student">
</bean>
<bean id="teacher" class="com.pojo.Teacher"></bean>
<bean id="course" class="com.pojo.Course"></bean>
</beans>
输出:
com.pojo.Student@5ec0a365 - com.pojo.Course@4fe3c938 - com.pojo.Teacher@5383967b
小结:@Resource的使用和@Autowired对于开发者来说,使用方法和实现效果基本一样,只是 @Autowired
按 byType 自动注入,而@Resource
默认按 byName 自动注入罢了。但是记住:@Resource注解无法对构造函数标注
@Resource注解对setter方法标注:
package com.pojo;
import javax.annotation.Resource;
public class Student {
private Course course;
private Teacher teacher;
@Resource
public void setCourse(Course course) {
this.course = course;
}
@Resource
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return super.toString() + " - " + course + " - " + teacher;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="student" class="com.pojo.Student">
</bean>
<bean id="teacher" class="com.pojo.Teacher"></bean>
<bean id="course" class="com.pojo.Course"></bean>
</beans>
输出:
com.pojo.Student@5f9d02cb - com.pojo.Course@63753b6d - com.pojo.Teacher@6b09bb57
小结:@Resource的使用和@Autowired对于开发者来说,使用方法和实现效果基本一样,只是 @Autowired
按 byType 自动注入,而@Resource
默认按 byName 自动注入罢了。但是记住:@Resource注解无法对构造函数标注
@Resource注解对构造函数标注:@Resource注解无法对构造函数标注
小结:@Resource的使用和@Autowired对于开发者来说,使用方法和实现效果基本一样,只是 @Autowired
按 byType 自动注入,而@Resource
默认按 byName 自动注入罢了。但是记住:@Resource注解无法对构造函数标注
2、@PostConstruct
或 @PreDestroy
这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。
package com.pojo;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Student {
private Course course;
private Teacher teacher;
@PostConstruct
public void postConstruct1() {
System.out.println("postConstruct Function is called");
}
@PreDestroy
public void preDestroy1() {
System.out.println("preDestroy Function is called");
}
public void setCourse(Course course) {
this.course = course;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return super.toString() + " - " + course + " - " + teacher;
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<bean id="student" class="com.pojo.Student">
<property name="teacher" ref="teacher"></property>
<property name="course" ref="course"></property>
</bean>
<bean id="teacher" class="com.pojo.Teacher"></bean>
<bean id="course" class="com.pojo.Course"></bean>
</beans>
加一个main函数,最后context.destroy();
public class TestSpring {
public static void main(String[] args) {
//访问applciationContext.xml
//ApplciatinoContext是Spring中的一个接口,它有两个实现类ClassPathXmlApplicationContext和FileSystemXmlApplicationContext
//Java中一般使用ClassPathXmlApplicationContext类创建Spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" });
Student student = (Student) context.getBean("student");
System.out.println(student);
context.destroy();
}
}
输出:
postConstruct Function is called
com.pojo.Student@50b494a6 - com.pojo.Course@3cef309d - com.pojo.Teacher@32709393
preDestroy Function is called
三、小结
本节介绍了Spring容器多个常用注解和非常用注解。
天天打码,天天进步!