Spring中用于管理bean的注解分为四大类:
1)、用于创建对象 @Component/@Coontroller@Service@Repository
2)、用于给对象中的属性注入值@Value、@Autowired、@Qualifier、@Resource
3)、用于改变作用范围@Scope
4)、用于定义生命周期@PostConstruct @PreDestroy
1、用于创建对象
用于创建对象的有四个:@Component,@Controller,@Service,@Repository
(1)、@Component注解
作用:把资源让Spring来管理、相当于在Xml中配置一个bean
属性:value:指定bean的id值、如果不指定value属性、默认bean的id是当前 类的类名、首字母小写
(2)、@Controller,@Service,@Repository
他们三个注解都是针对一个的衍生注解,他们的作用及属性都是一模一样的。
他们只不过是提供了更加明确的语义化。
@Controller:一般用于表现层的注解。
@Service:一般用于业务层的注解。
@Repository:一般用于持久层的注解。
@Service的用法:修改UserServiceImpl类,把@Component改成@Service
//@Component("userService")
@Service("userService")//@Service加在业务层的bean,value属性指定bean的id
public class UserServiceImpl implements UserService{
@Override
public void saveUser() {
System.out.println("业务层:用户保存...");
}
}
@Repository的用法:创建UserDao接口:
创建UserDao.java接口和UserDaoImpl.java实现类
package com.day01.dao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:00 2018/11/8
*/
public interface UserDao {
public abstract void save();
}
package com.day01.dao.Impl;
import com.day01.dao.UserDao;
import org.springframework.stereotype.Repository;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:01 2018/11/8
*/
@Repository("userDao")//@Repository加在dao层的bean,value属性指定bean的id
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("持久层。。。。");
}
}
applicationContext.xml、要把扫描的包定义为com.day01,不然的其它包的注解就不能识别了
<?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:component-scan base-package="com.day01"/>
</beans>
测试
package com.day01.test;
import com.day01.dao.UserDao;
import com.day01.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 13:35 2018/11/8
*/
public class TestIOC {
@Test
public void test2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) ac.getBean("userDao");
userDao.save();
}
}
@Controller:
@Controller("userAction")//@Controller加在web层的bean,value属性指定bean的id
public class UserAction {
}
2、用于给对象属性注入值
用于给对象属性注入数据的注解有:
@Value、@Autowired、@Qualifier、@Resource
相当于:<property name="" ref=""> /<property name="" value="">
<bean id="people" class="com.day01.domain.People">
<property name="name" value="小刚"></property>
<property name="address" value="上海"></property>
<property name="car" ref="car"></property>
</bean>
(1)、@Value
作用:注入基本数据类型和String类型数据
属性:value:用于指定值
修改UserDaoImpl.java、增加一个字符串属性name、通过@Value注解实现
package com.day01.dao.Impl;
import com.day01.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:01 2018/11/8
*/
@Repository("userDao")//@Repository加在dao层的bean,value属性指定bean的id
public class UserDaoImpl implements UserDao {
@Value("小罗")//@Value给基本类型和字符串类型注入值,value属性指定要注入的值
private String name;
@Override
public void save() {
System.out.println("持久层。。。。"+name);
}
}
测试
@Test
public void test2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) ac.getBean("userDao");
userDao.save();
}
(2)、@Autowired
作用:
自动按照类型注入。
当使用注解注入属性时,set方法可以省略。它只能注入其他bean类型。当有多个类型匹配时,
使用要注入的对象变量名称作为bean的id,在spring容器查找,找到了也可以注入成功。找不到就报错。
修改UserServiceImpl类、增加一个对象属性userDao、现通过@Autowired给userDao注入值
package com.day01.service.Impl;
import com.day01.dao.UserDao;
import com.day01.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 12:22 2018/11/8
*/
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("小罗")//@Value给基本类型和字符串类型注入值,value属性指定要注入的值
private String name;
@Autowired //注入对象类型、招照类型注入
private UserDao userDao;
@Override
public void saveUser() {
System.out.println("业务层:保存用户。。。。。。"+name);
userDao.save();
}
}
UserDaoImpl.java
package com.day01.dao.Impl;
import com.day01.dao.UserDao;
import org.springframework.stereotype.Repository;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:01 2018/11/8
*/
@Repository("userDao")//@Repository加在dao层的bean,value属性指定bean的id
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("持久层。。。。");
}
}
测试类TestIOC.java
package com.day01.test;
import com.day01.dao.UserDao;
import com.day01.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 13:35 2018/11/8
*/
public class TestIOC {
/**
* 测试注解
*/
@Test
public void test1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.saveUser();
}
}
(3)、@Qualifier
作用:
在自动按照类型注入的基础之上,再按照Bean的id注入。
它在给字段注入时不能独立使用,必须和@Autowire一起使用;但是给方法参数注入时,可以独立使用。
属性:value:指定bean的id。
创建UserDao接口的第二个实现类UserDaoImpl2.java
package com.day01.dao.Impl;
import com.day01.dao.UserDao;
import org.springframework.stereotype.Repository;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:36 2018/11/8
*/
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao {
@Override
public void save() {
System.out.println("持久层:2222.。。。。。。。");
}
}
测试
@Test
public void test1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.saveUser();
}
测试发现、UserServiceImpl中注入的还是第一个UserDaoImpl,因为当有多个bean都满足的情况下,
优先注入bean的id与属性的名字一样的bean;想指定注入UserDaoImpl2,需要使用@Qualifier注解根据名字来注入
UserServiceImpl.java
package com.day01.service.Impl;
import com.day01.dao.UserDao;
import com.day01.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 12:22 2018/11/8
*/
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("小罗")//@Value给基本类型和字符串类型注入值,value属性指定要注入的值
private String name;
@Autowired //注入对象类型、招照类型注入
@Qualifier("userDao2")
private UserDao userDao;
@Override
public void saveUser() {
System.out.println("业务层:保存用户。。。。。。"+name);
userDao.save();
}
}
测试TestIOC.java
package com.day01.test;
import com.day01.dao.UserDao;
import com.day01.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 13:35 2018/11/8
*/
public class TestIOC {
/**
* 测试注解
*/
@Test
public void test1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.saveUser();
}
}
修改UserServiceImpl.java再次测试、就会发现UserServiceImpl中注入的是UserDaoImpl2
(4)、@Resource
作用:直接按照Bean的id注入。它也只能注入其他bean类型。
属性:name:指定bean的id。
修改UserServiceImpl类,使用@Resource给userDao注入值。@Resource是按照bean的id来注入,只能注入对象类型
UserDaoImpl2.java实现类
package com.day02.dao.Impl;
import com.day02.dao.UserDao;
import org.springframework.stereotype.Repository;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:36 2018/11/8
*/
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao {
@Override
public void save() {
System.out.println("持久层:2222.。。。。。。。");
}
}
UserServiceImpl.java实现类
package com.day02.service.Impl;
import com.day02.dao.UserDao;
import com.day02.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 12:22 2018/11/8
*/
//@Component("userService")
//@Scope("singleton")
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("小罗")//@Value给基本类型和字符串类型注入值,value属性指定要注入的值
private String name;
// @Autowired //注入对象类型、招照类型注入
// @Qualifier("userDao")
@Resource(name="userDao2")
private UserDao userDao;
public UserServiceImpl() {
System.out.println("调用了无参构造。。。。。");
}
@PostConstruct
public void init(){
System.out.println("---------------调用init方法。。。。");
}
@Override
public void saveUser() {
System.out.println("业务层:保存用户。。。。。。"+name);
userDao.save();
}
@PreDestroy
public void destory(){
System.out.println("-------------------调用了destroy方法。。。。。");
}
}
测试类:TestIOC.java
package com.day02.test;
import com.day02.dao.UserDao;
import com.day02.service.UserService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 13:35 2018/11/8
*/
public class TestIOC {
private ClassPathXmlApplicationContext ac = null;
@Before
public void setUp(){
ac= new ClassPathXmlApplicationContext("applicationContext.xml");
}
/**
* 测试注解
*/
@Test
public void test1(){
UserService userService = (UserService) ac.getBean("userService");
userService.saveUser();
ac.close();
}
}
注意:@Resource注解不起作用情况、本人亲测JDK9不起作用、换成JDK8就好了。
3、用于改变作用域范围
@Scope
作用:指定bean的作用范围
属性:value:指定范围的值。取值:singleton prototype request session globalsession
修改UserServiceImpl,在该类上加@Scope注解,指定该类是多例的的,默认是单例的。给该类显示指定一个无参构造方法,方便测试
package com.day01.service.Impl;
import com.day01.dao.UserDao;
import com.day01.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 12:22 2018/11/8
*/
//@Component("userService")
@Service("userService")
@Scope("prototype")
public class UserServiceImpl implements UserService {
public UserServiceImpl() {
System.out.println("调用了无参构造。。。。。");
}
@Value("小罗")//@Value给基本类型和字符串类型注入值,value属性指定要注入的值
private String name;
@Autowired //注入对象类型、招照类型注入
@Qualifier("userDao2")
//@Autowired()
private UserDao userDao;
@Override
public void saveUser() {
System.out.println("业务层:保存用户。。。。。。"+name);
userDao.save();
}
}
测试TestIOC.java
@Test
public void test3(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ac.getBean("userService");
UserService userService1 = (UserService) ac.getBean("userService");
System.out.println(userService1+ " = " +userService);
}
4、用于定义生命周期
相当于applicationContent.xml中的
<bean id="" class="" init-method="" destroy-method="" />
@PostConstruct注解 @PreDestory注解
(1)、@PostConstruct
说明:@PostConstruct加在方法上,指定bean对象创建好之后,调用该方法初始化对象,类似于xml的init-method方法。修改UserServiceImpl类,在其中增加一个init方法,在该方法上指定@PostConstruct注解
(2)、@PreDestory
@PreDestory加在方法上,指定bean销毁之前,调用该方法,类似于xml的destory-method方法。修改UserServiceImpl类,在该类中增加一个destroy方法,在该方法上加@PreDestroy注解
UserDaoImpl.java
package com.day02.dao.Impl;
import com.day02.dao.UserDao;
import org.springframework.stereotype.Repository;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:36 2018/11/8
*/
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao {
@Override
public void save() {
System.out.println("持久层:2222.。。。。。。。");
}
}
UserServiceImpl.java
package com.day02.service.Impl;
import com.day02.dao.UserDao;
import com.day02.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 12:22 2018/11/8
*/
//@Component("userService")
//@Scope("singleton")
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("小罗")//@Value给基本类型和字符串类型注入值,value属性指定要注入的值
private String name;
// @Autowired //注入对象类型、招照类型注入
// @Qualifier("userDao")
@Resource(name="userDao2")
private UserDao userDao;
public UserServiceImpl() {
System.out.println("调用了无参构造。。。。。");
}
@PostConstruct
public void init(){
System.out.println("---------------调用init方法。。。。");
}
@Override
public void saveUser() {
System.out.println("业务层:保存用户。。。。。。"+name);
userDao.save();
}
@PreDestroy
public void destory(){
System.out.println("-------------------调用了destroy方法。。。。。");
}
}
TestIOC.java测试类
package com.day02.test;
import com.day02.dao.UserDao;
import com.day02.service.UserService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 13:35 2018/11/8
*/
public class TestIOC {
private ClassPathXmlApplicationContext ac = null;
@Before
public void setUp(){
ac= new ClassPathXmlApplicationContext("applicationContext.xml");
}
/**
* 测试注解
*/
@Test
public void test1(){
UserService userService = (UserService) ac.getBean("userService");
userService.saveUser();
ac.close();
}
}
注意:@PreDestory和@PostConstruct在JDK9上不起作用、换成JDK8就好了。
注解总结:
与创建Bean对象相关:
@component @Controller @Service @Repository
与属性注入值相关:
@Value @Autowired @Qulifier @Resource
与范围相关
@Scope
与生命周期相关
@PostConstruct @PreDestroy
5、XML和注解的比较
注解的优势:配置简单,维护方便。(我们找到了类,就相当于找到了配置)
XML的优势:修改时,不用改源码。不涉及重新编译和部署。
基于xml配置 | 基于注解配置 | |
---|---|---|
Bean定义 | <bean id="" class="" /> | @Component衍生类@Repository@Service@Controller |
Bean名称 | 通过id或name指定 | @Component("person") |
Bean注入 | <property>或者通过p命名空间 | @Autowired按类型注入@Qualifier按名称注入 |
生命令过程、Bean作用范围 | init-method destroy-method 范围Scope属性 | @PostConstruct 初始化 @PreDestroy销毁 @Scope设置作用范围 |
适合场景 | Bean来自第三方、使用其它 | Bean的实现类由用户自已开发 |