[学习笔记] Spring注解开发

3 篇文章 0 订阅

DI注解

@Autowired

看看之前开发的案例, 两个bean(bean1和bean2), bean1依赖bean2

bean代码:

public class Bean1 {
	
	private Bean2 b2;
	public void setB2(Bean2 b2) {
		this.b2 = b2;
	}

	@Override
	public String toString() {
		return "Bean1 [b2=" + b2 + "]";
	}
}

class Bean2{
	
}

配置文件中这样配:

    <bean id="bean1" class="_03_anno._1_start.Bean1" />
    <bean id="bean2" class="_03_anno._1_start.Bean2" />

这时打印一个bean1对象, 其中的bean2属性是空的(很好理解, 因为没有给bean1注入bean2):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:_03_anno/_1_start/AppTest.xml")
public class App {
	
	@Autowired
	private Bean1 b1;
	
	@Test
	public void testBean1(){
		System.out.println(b1);
	}
}

之前开发时是在bean元素里配置property元素, 然后再注入. 现在使用@AutoWired简单些, 直接在属性上面或者属性的setter方法上面配置@AutoWired即可

package _03_anno._1_start;

import org.springframework.beans.factory.annotation.Autowired;

public class Bean1 {
	
	@Autowired
	private Bean2 b2;

	@Override
	public String toString() {
		return "Bean1 [b2=" + b2 + "]";
	}
}

class Bean2{
	
}

在属性上配置时甚至可以不要setter方法

注意: 最好还是在配置文件中配上<context:annotation-config>, 表示DI注解解析器

    <context:annotation-config />
    
    <bean id="bean1" class="_03_anno._1_start.Bean1" />
    <bean id="bean2" class="_03_anno._1_start.Bean2" />

说明:

  • @AutoWired注解默认按照类型去找, 如果找不到这个类则报错. 可以通过@AutoWired(required=false)来解决这个问题

  • 因为@AutoWired注解默认按照类型去找, 如果一个类型的bean配置有多个对象(如下面情况)则报错

    <bean id="bean1_01" class="_03_anno._1_start.Bean1" />
    <bean id="bean1_02" class="_03_anno._1_start.Bean1" />
    <bean id="bean2" class="_03_anno._1_start.Bean2" />

使用@Qualifier(bean.id")的方式可以按照类型去寻找对象, 找到多个再按id去寻找(如果找不到则报错)

	@Autowired
	@Qualifier("bean1_01")
	private Bean1 b1;
	
	@Test
	public void testBean1(){
		System.out.println(b1);
	}

@Resource

@Resource注解和@AutoWired功能其实是一样的, 且都需要配置<context:annotation-config />.

不同点:

  • @AutoWired注解是spring提供的, @Resource注解是JavaEE官方提供的

  • @AutoWired先按照类型寻找bean, 再按照名称或者id; @Resource则先按照名称, 再按照类型


@Value

@AutoWired注解用于给对象属性注入值, 而**@Value注解用于给常量注入值**, 相当于bean的property属性. 下面演示:

bean:

package _03_anno._2_value;

import org.springframework.beans.factory.annotation.Value;

public class ValueBean {

	private int port;

	@Override
	public String toString() {
		return "ValueBean [port=" + port + "]";
	}
}

配置文件:

	<bean id="valueBeanId" class="_03_anno._2_value.ValueBean" />

测试代码:

	@Autowired
	private ValueBean valueBean;
	
	@Test
	public void testValueBean(){
		System.out.println(valueBean);
	}

现在打印出来肯定是空的(port=8080), 因为没有注入值, 之前我们是在配置文件中添加<property>元素, 在其中设置value属性, 现在使用注解方式:

	@Value("8080")
	private int port;

	@Override
	public String toString() {
		return "ValueBean [port=" + port + "]";
	}

这样就能输出"port=8080"

然而这样做显然没有什么用, 因为我还不如直接写private int port = 8080;, 但为了降低耦合度, 可以将值写在properties文件中, 让spring加载配置文件即可

新建service.properties文件:

service.port=8080

此时的xml文件需要加载service.properties文件:

    <context:annotation-config />
    <context:property-placeholder location="classpath:_03_anno/_2_value/service.properties" />
    
    <bean id="valueBeanId" class="_03_anno._2_value.ValueBean" />

现在的bean应该这样写(解析properties文件):

	@Value("${service.port}")
	private int port;

	@Override
	public String toString() {
		return "ValueBean [port=" + port + "]";
	}

测试代码不变, 此时就能正常输出port=8080


IoC注解

@Component

之前我们让spring帮我们管理bean使用的是xml配置方式, 但这样有点繁琐, 使用注解可以简单很多

bean

package _03_anno._3_component;

import org.springframework.stereotype.Component;

@Component("componentBeanId")
public class ComponentBean {

}

@Component注解即代表控制反转, 括号里的value值相当于xml配置中的id属性值. 因为贴在哪个类上就代表管理哪个类, 所以不需要类似xml中的class属性

但这样还不够. 类似使用注入注解需要在xm文件中配置"DI注解解析器", 使用IoC注解需要在xm文件中配置"IoC注解解析器", 用于解析IoC注解(即@Component)

	<context:component-scan base-package="_03_anno._3_component" />

base-package属性代表包名, 表示从哪个包下去扫描组件注解

bean组件版型

其实除开@Component注解另外还有3个组件, 但这4个组件功能是一样的, 下面简单说下区别:

  • @Component: 泛指组件, 当不知道如何归类时使用这个

  • @Repository: Dao组件

  • @Service: 业务层组件

  • @Controller: 控制层组件

优先使用下面3个.


作用域和生命周期配置

之前配置bean的作用域(单例还是多例)和生命周期方法是在xml中配置的, 如下:

bean:

package _03_anno._4_lifecycle;

public class Bean1 {
	
	public Bean1(){
		System.out.println("Bean1 constructor");
	}
	
	public void open(){
		System.out.println("Bean1.open()");
	}
	
	public void doWork(){
		System.out.println("Bean1.doWork()");
	}
	
	public void destroy(){
		System.out.println("Bean1.destroy()");
	}
}

配置文件:

	<bean id="bean1" class="_03_anno._4_lifecycle.Bean1" 
    	scope="prototype" init-method="open" destroy-method="destroy" />

现在使用注解配置, scope属性对应@Scope, init-method属性对应@PostConstruct, destroy-method属性对应PreDestroy, 如下演示:

bean:

package _03_anno._4_lifecycle;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class Bean1 {
	
	public Bean1(){
		System.out.println("Bean1 constructor");
	}
	
	public void open(){
		System.out.println("Bean1.open()");
	}
	
	public void doWork(){
		System.out.println("Bean1.doWork()");
	}
	
	public void destroy(){
		System.out.println("Bean1.destroy()");
	}
}

配置文件中需添加<context:component-scan base-package="" >

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值