Spring学习
- 5 基于注解方式创建对象
- 6 基于注解注入属性
5 基于注解方式创建对象
注解是代码的特殊标记,可以简化xml配置,格式:@注解名称(属性名称=属性值),可以作用在类、方法、属性上
以下注解都可以创建bean实例
- @Component
- @Service
- @Controller
- @Repository
创建一个bean2.xml文件,其中component-scan是组件扫描,默认是全扫描,会扫描包中所有的注解并将它们加入到bean容器,可以扫描多个包(包用逗号隔开),此外,还可以通过use-default-filters=“false” 和context:include-filter 设置只扫描哪些内容或context:exclude-filter设置哪些内容不进行扫描
<?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
https://www.springframework.org/schema/context/spring-context.xsd">
<!--component-scan组件扫描-->
<context:component-scan base-package="springstudy1"></context:component-scan>
<!-- type="annotation"表示按照注解进行排除,指定注解不加入bean容器中,此处Component注解不会加入bean容器 -->
<context:component-scan base-package="springstudy1">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Component"/>
</context:component-scan>
<!-- 排除指定包springstudy下的User类的扫描,不会将该类的注解加入bean容器-->
<context:component-scan base-package="springstudy">
<context:exclude-filter type="assignable"
expression="springstudy.User"/>
</context:component-scan>
<!-- 排除扫描符合正则表达式的类,此处排除springstudy包下的所有类,不会将这些类的注解加入bean容器-->
<context:component-scan base-package="springstudy1">
<context:exclude-filter type="regex"
expression="springstudy.*"/>
</context:component-scan>
</beans>
注:上述代码中若注解已经加入bean容器,之后通过exclude-filter排除注解没有用,context:include-filter和exclude-filter用法类似,type的属性值相同,不过多说明
创建User类,添加@Component注解,其中value可以省略,默认值是类名称,首字母小写
package springstudy1;
import org.springframework.stereotype.Component;
@Component(value = "user") //等价于在xml文件中添加<bean id="user" class="springstudy1.User"></bean>
public class User {
public void add() {
System.out.println("add...");
}
}
创建Test类
package springstudy1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
User user = context.getBean("user", User.class);
user.add();
}
}
补充:通过@Bean注解创建对象
创建Card类,使用@Bean注解创建User对象,name默认是类名(首字母小写)
package springstudy1;
import org.springframework.context.annotation.Bean;
public class Card {
@Bean(name="test")
public User test() {
return new User();
}
}
修改Test类
package springstudy1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Card.class);
User user = (User) context.getBean("test");
user.add();
}
}
6 基于注解注入属性
- @Autowired,根据属性类型进行自动装配
- @Qualifier,根据名称进行注入,和@Autowired 一起使用
- @Resource,可以根据类型注入,可以根据名称注入
- @Value,注入普通类型属性
@Autowired根据属性类型选择bean,但有时容器中会有多个相同类型的bean,在这种情况下,注入不会成功,因为 Spring 不知道需要注入哪个 bean。这时需要通过@Qualifier根据名称选择注入哪个bean,也可以使用 @Primary 注解来简化这种情况
@Component
@Primary
class Car implements Vehicle {}
@Component
class Bike implements Vehicle {}
@Component
class Driver {
@Autowired
Vehicle vehicle;
}
@Component
class Biker {
@Autowired
@Qualifier("bike")
Vehicle vehicle;
}
上述代码中,Car注解了@Primary。因此,在Driver类中,Spring 注入了一个Car bean。在 Biker bean 中,vehicle 字段的值将是 Bike 对象,因为它注解了 @Qualifier 并且指定了bean 名称。
此外还可以在声明bean和注入bean时添加@Qualifier也可以起到过滤其他同类型bean的效果
@Component
@Primary
class Car implements Vehicle {}
@Component
@Qualifier
class Bike implements Vehicle {}
@Component
class Driver {
@Autowired
@Qualifier
Vehicle vehicle;
}
上述代码会注入Bike bean
@Resource有两个重要的属性:name和type,Spring会将@Resource注解的name属性解析为bean的名字(id属性值),而type属性则解析为bean的类型(class属性值)。如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时会尝试按名称查找,如果未找到,则按类型查找。
效率好低。。。
除夕快乐!!!
@value介绍
@value有两种使用格式,@value(${})和@value(#{}),其中#{}可以包含${},即@value(#{${}})
@value(${})常用来注入配置文件的数据(如连接数据库的数据),需要结合@PropertySource注解才能使用
对于@value(#{}),{}中的内容被认为是SpEL(Spring Expression Language)即Spring表达式语言,可以干以下几件事
- 注入普通字符串
- 注入操作系统属性
- 注入表达式结果
- 注入其他Bean属性
- 注入集合
- 注入文件资源
- 注入URL资源
注:${}中直接使用“:”对未定义或为空的值进行默认值设置,而#{}则需要使用“?:”对未设置的属性进行默认值设置
在src目录下创建配置文件test.properties
festival=除夕
hongbao=200,400,600
foods={'food1':'牛肉炒红椒','food2':芹菜炒牛肉','food3':'牛肝炖汤','food4':'滑肉'
//通过@value(${})获得配置文件中的数据
//可以是@PropertySource(value = {"file:文件绝对路径"}, encoding="utf-8")
/*多个配置文件
方式1:@PropertySource("classpath:redis.properties","classpath:database.properties")
方式2:@PropertySources({ @PropertySource("classpath:redis.properties"),
@PropertySource("classpath:database.properties")})
*/
@PropertySource("classpath:test.properties")//注意路径,此处配置文件地址类似./src/test.properties
@value(${festival:除夕}) //如果festival不存在,默认注入 除夕 ,不用加引号
private String festival;
//被static修饰的变量通过@Value会注入失败,可通过setter方式进行注入该属性
//注入普通字符串,相当于直接给属性默认值
@Value("程序新视界")
private String wechatSubscription;
//注入操作系统属性
@Value("#{systemProperties['os.name']}")
private String systemPropertiesName;
//注入表达式结果
@Value("#{ T(java.lang.Math).random() * 100.0 }")
private double randomNumber;
//注入其他Bean属性:注入config对象的属性tool
@Value("#{config.tool}")
private String tool;
//注入集合
//Spring默认情况下会以“,”进行分割,转换成对应的数组或列表
@Value("#{${hongbao}.split(',')}")
private List<Integer> numList;
//或者private int[] numArray;
//Map
@Value("#{${foods}}")
private Map<String, String> foods;
//如果需要获取 Map 中特定 Key 的 Value,只需在表达式中添加 Key 的名称即可:
@Value("#{${foods}.food1}")
private String food1;
//如果不确定 Map 是否包含某个 Key,可以选择一个更安全的表达式,它不会抛出异常,但会在找不到 Key 时将值设置为 null:
@Value("#{${foods}['unknownKey']}")
private String unknownMapKey;
//注入文件资源
@Value("classpath:config.xml")
private Resource resourceFile;
//注入URL资源
@Value("http://www.choupangxia.com")
private URL homePage;