首先理解什么是Bean。凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性,把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了,就可以去使用了。什么是注解。注解就是@XX,如果你使用@XX,Spring就会过来看看,帮你注册一个Bean或者从Spring IOC中拿Bean。
大体上注解分成两种。一是注册Bean,就是将你的类或者方法转化成一个Bean,注册到Spring IOC中,如@Component , @Repository , @ Controller , @Service;另一种,就是从Spring IOC中获取一个Bean,如@Autowired , @Resource。
前期准备
打算使用代码来讲解注解,这就需要先创建例程:
有Tiger,Monkey,ICar,BenzCar,BMWCar
public class Tiger {
private String tigerName="TigerKing";
public String toString(){
return "TigerName:"+tigerName;
}
}
public class Monkey {
private String monkeyName = "MonkeyKing";
public String toString(){
return "MonkeyName:" + monkeyName;
}
}
public interface ICar {
public String getCarName();
}
public class BenzCar implements ICar{
public String getCarName(){
return "Benz car";
}
}
public class BMWCar implements ICar{
public String getCarName(){
return "BMW car";
}
}
常用的注解
1、@Autowired
顾名思义,自动装配。按照类型匹配,在容器中查找匹配的Bean。当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
先注册一些Bean。包括tiger和monkey
<?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:p="http://www.springframework.org/schema/p"
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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<context:component-scan base-package="com.spring" />
<bean id="tiger" class="com.spring.model.Tiger" />
<bean id="monkey" class="com.spring.model.Monkey" />
</beans>
如果不是Spring,那我们使用的时候就是 Tiger tiger = new Tiger( )。@Autowired十分方便我们将获取实例。
public class Zoo {
@Autowired
private Tiger tiger;
@Autowired
private Monkey monkey;
}
@Autowired会自动匹配类型,并自动注入进来。如果没有事先注入的Bean,而使用@Autowired就会在编译时候报错,有没有优化方法,有。
@Autowired(required=false)
private Tiger tiger;
这样在找不到Bean时也不会报错,只不过tiger属性为null。
2、@Qualifier
如果容器中有一个以上匹配的Bean,则可以通过@Qualifier注解限定Bean的名称。
向Spring IOC添加新的注解,宝马车和奔驰车,这两个车都是继承ICar。
<bean id="bmwCar" class="com.spring.service.impl.BMWCar" />
<bean id="benz" class="com.spring.service.impl.BenzCar" />
如果你正好要出行,这个时候需要一个车,好,获取一个呗:
@Autowired
private ICar car;
这个时候Spring这个管家就生气了,什么鬼,到底什么车,奔驰还是宝马。如果说ICar只有一个继承实现类,那好说,直接使用一个就好了。但是多个实现就有问题了,不知道使用那个实现类。这个时候使用@Qualifier 来指明使用哪个Bean。所以决定以后出行都用宝马。此处会注入名为”bmwCar”的Bean。
@Autowired
@Qualifier("bmwCar")
private ICar car;
3、@Resource
这个@Resource注解与@Autowired注解作用非常相似。
@Resource(name="tiger")
private Tiger tiger;
@Resource(type=Monkey.class)
private Monkey monkey;
这是详细一些的用法,说一下@Resource的装配顺序:
1. @Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
2. 指定了name或者type则根据指定的类型去匹配bean
3. 指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错
然后,区分一下@Autowired和@Resource两个注解的区别:
1. @Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配
2. @Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了
4、@Service
通过上面的例子会发现,好累,每次都要写个xml去存放Spring的Bean,一旦项目变大,那这个xml会变得非常庞大和复杂,难以维护。有没有方法解决,有的。@Service。@Service的作用就是将注解的地方生成一个Bean注册到Spring IOC中管理。
@Service
public class Monkey {
private String monkeyName = "MonkeyKing";
public String toString(){
return "MonkeyName:" + monkeyName;
}
}
上述就是将Monkey这个类生成一个Monkey Bean注册到Spring IOC中。@Service注解,其实做了两件事情:
1. 声明Monkey.java是一个bean,这点很重要,因为Monkey.java是一个bean,其他的类才可以使用@Autowired将Monkey作为一个成员变量自动注入。
2. Monkey.java在bean中的id是”monkey”,即类名且首字母小写。
如果有一些特殊的癖好,我不要小猴,我要大猴,怎么办,那就注册的时候指定名称@Service(“Monkey”)。
5、@Scope
Spring 管家有一个有癖好的人。Spring默认产生的bean是单例的。默认是”singleton”即单例,”prototype”表示原型即每次都会new一个新的出来。
@Service("monkey")
@Scope("prototype")
public class Monkey {
private String monkeyName = "MonkeyKing";
public String toString(){
return "MonkeyName:" + monkeyName;
}
}
6、@Controller
@Controller对应表现层的Bean,也就是Action。这个也是与@Service相似,向Spring注册一个Bean,@Service是对应的是业务层Bean。
7、@ Repository
@Repository对应数据访问层Bean。
@Repository("userDao")
public class UserDaoImpl implements BaseDao {
………
}
@Repository(“userDao”)注解是告诉Spring,让Spring创建一个名字叫”userDao”的UserDaoImpl实例。
当需要使用Spring创建的名字叫”userDao”的UserDaoImpl实例时,就可以使用@Autowired(“userDao”)注解告诉Spring,Spring把创建好的userDao注入即可。
@Autowired("userDao")
private BaseDao userDao;
@Repository,@Service和@Controlle这三个没什么功能上的差别,差别只是在语义上,@Repository/@Service/@Controller分别代表了特定语义的类, @Repository:用于标注数据访问组件,即DAO组件我们注解这个类,更多的是对它有个数据库操作的管理,比如你继承了spring自己的hibernateDAo这样的东西,那怎么给你注入一些数据库操作的元素了,就靠它了,所以这个不是随便注释的。
8、@ Bean 和 @Configuration
@Bean明确地指示了一种方法,什么方法呢?!产生一个bean的方法,并且交给Spring容器管理;从这我们就明白了为啥@Bean是放在方法的注释上了,因为它很明确地告诉被注释的方法,你给我产生一个Bean,然后交给Spring容器,剩下的你就别管了。@Bean常常和@Configuration配合使用。
@Configuration可理解为用spring的时候xml里面的< beans >标签
@Bean可理解为用spring的时候xml里面的< bean >标签
@Configuration
public class ExampleConfiguration {
@Value("com.mysql.jdbc.Driver")
private String driverClassName;
@Value("jdbc://xxxx.xx.xxx/xx")
private String driverUrl;
@Value("${root}")
private String driverUsername;
@Value("123456")
private String driverPassword;
@Bean(name = "dataSource")
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(driverUrl);
dataSource.setUsername(driverUsername);
dataSource.setPassword(driverPassword);
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
这样就可以在项目中使用@Autowired去获取实例。
@Autowired
private DataSource dataSource;
9、@ Value
@ Value是用于简化读取properties文件中的配置值,spring支持@value注解的方式来获取,这种方式大大简化了项目配置,提高业务中的灵活性。
两种使用方法
@Value("#{configProperties['key']}")
@Value("${key}") <- 推荐这种
9.1 第一种配置
在配置文件中写上
<!-- @Value -->
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:hahaha.properties</value>
</list>
</property>
</bean>
并在src下添加配置文件hahaha.properties,内容如下:
my.name=hahaha
my.age=27
9.2 第二种配置
在配置文件中写上
<!-- @Value -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:hahaha.properties</value>
</list>
</property>
</bean>
并在src下添加配置文件hahaha.properties
10、@RequestMapping
用来处理请求地址映射的注解。
@Controller
//设置想要跳转的父路径
@RequestMapping(value = "/Controllers")
public class StatisticUserCtrl {
// 设置方法下的子路经
@RequestMapping(value = "/method")
public String helloworld() {
return "helloWorld";
}
}
其对应的 action就是“/Controllers/method”,通过 “http://localhost:8080/Controllers/method ”就可以访问该方法。
11、@ResponseBody
该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中,返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用。方法无法返回jsp页面,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。
12、@RequestBody
@RequestBody 注解则是将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。
用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上
再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
@RequestMapping(value = "/main/addUserInfo")
public ResultBean addUserInfo(@RequestBody UserInfo userInfo) {
}
GET请求中,因为没有HttpEntity,所以@RequestBody并不适用。
POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。
13、@RequestParam
指定输入的参数。
@RequestMapping(value = "/main/addName")
public ResultBean addName(@RequestParam(value = "name", defaultValue = "haha") String userInfo) {
}
14、@RestController
该注解其实就是@ResponseBody + @Controller, @Controller配合视图解析器InternalResourceViewResolver才行。如果需要返回JSON,XML或自定义mediaType内容到页面,则需要RestController。
15、@Scheduled
这个是定时器注解。可以定时或者定间隔的启动某个任务。它带有三种定时运行方式,fixedDelay、fixedRate和cron表达式。
fixedDelay <- 上一次任务结束后,完整的延迟时间后再执行。
fixedRate <- 按照整点时间划分,如果上一次任务没执行完,就等他执行完后立马执行,任务持续累加、阻塞。
cron <- 定制化定时时间,上一次任务结束后的最近整点时间开始执行。
一张图看懂运行方式,图片来自:https://blog.csdn.net/applebomb/article/details/52400154
initialDelay这个参数用来延迟启动之用。