spring-beans约束文件
引入Lombok
org.projectlombok lombok 1.18.16
有参构造方法
@AllArgsConstructor
public class Person {
private Integer id;
private String name;
public void sayHello(String name){
System.out.println(this.id+this.name+" say hello to " + name);
}
}
注册bean
测试类
public class IocTest {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("spring-ioc-cfg.xml");
Person person = (Person) ctx.getBean("Person");
person.sayHello("luyi");
}
}
测试结果
1at say hello to tt有参构造方法注入缺陷
public class Person {
private Integer id;
private String name;
private String nickname;
public Person(String name, String nickname) {
this.name = name;
this.nickname = nickname;
}
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
public void sayHello(String name){
System.out.println(this.id+this.name+"["+this.nickname+"]" +" say hello to " + name);
}
}
这时我们传入如下参数
结果: nullperson1[person2] say hello to at 这时spring调用了Person的public Person(String name, String nickname)方法 。但是,如果我们传入下面的参数:
结果:null1[person2] say hello to at这个时候还是调用的Person的 Person(String name, String nickname)方法,实际上我们要调用的是public Person(Integer id, String name) 方法,Spring没有办法帮我们调用到。因为Spring调用有参构造方法的逻辑按照构造方法的定义顺序,从上往下找到第一个满足参数个数匹配的方法来调用。
1、基于Setter的注入(重要)setter注入时Spring中最流行的注入方式,它的原理是先调用无参构造方法,然后调用对应的set方法来为属性赋值。用setter的方式可以解决有参构造方法注入的问题,并且可以提高可读性。
1、改造Person
@Setter //Setter注解自动为属性设置set方法
public class Person {
private Integer id;
private String name;
private String nickName;
public void sayHello(String name){
System.out.println(this.id+this.name+"["+this.nickName+"]" +" say hello to " + name);
}
}
2、用过property设置属性
2、xml装配bean
Spring提供了三种方式来对Bean进行配置
1、在xml文件中配置
2、在Java接口和实现类中配置
3、隐式Bean的发现机制和自动装配原则
分析bean标签1、bean标签有一个id属性,这个id属性就是为bean取的一个全局唯一的名字。这个属性不是一个必须的属性,,如果没有声明它,那么Spring会采用"全限定名#{number}"的方式自动为我们生成一个编号,number从0开始计数。比如我们声明了两个Person对象,如下:
这个时候我们再用原来的方式获取Person就获取不到了,因为我们的id时Spring自动生成的,我们并没有指定。
public class IocTest {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("spring-ioc-cfg.xml");
//Person person = (Person)ctx.getBean("com.tgxit.spring.atioc.beans.Person#0");
Person person = (Person) ctx.getBean(Person.class.getName()+"#0");
person.sayHello("周杰伦");
}
}
2、class就是我们要注入的对象类型,这里填写一个类的全限定名
3、property元素定义类的属性,其中name表示属性名,value表示属性值
3、装配集合(重要)通过property标签的方式实现注入。但是这个对于一些基本数据类型和String类型的数据注入比较方便。如果我们要注入的类型是集合类型(List、Set、Map、Properties)怎么办?
1、接下来我们定义一个新的类:
@Data
public class Coder {
private String name;
private List languages;
private Set friends;
private Map houses;
private Properties properties;
}
2、在配置文件中注入Coder:
java c++ sql shell javascript
肖战 王一博 迪丽热巴 蔡徐坤 180 140 18
3、调用测试:
private static void testCoder(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("spring-ioc-cfg.xml");
Coder coder = (Coder) ctx.getBean("coder");
System.out.println(coder);
}
4、复杂bean装配 (重要)
1、定义三个类
@Data
public class User {
private Integer id;
private String name;
}
@Data
public class Role {
private Integer id;
private String name;
}
@Data
public class UserRole {
private Integer id;
private List users;
private Map map;
}
2、注入的思路,首先把以来的对象给注入了,然后再来注入自己:
3、测试并打印输出结果:
private static void testComplexBean(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("spring-ioc-cfg.xml");
UserRole userRole = (UserRole) ctx.getBean("userRole");
System.out.println(userRole);
}
5、命名空间的装配(了解)
Spring注解方式装配Bean
1、概述
通过之前的学习,我们已经知道如何使用XML的方式去装于Bean但是更多的时候我们已经不再推荐使用XAM的方式去装面Bean,更多时候会考虑使用注解的方式去装于Pen。使用注郓的方式可以减少AM的配置,并且注解功能更为强大,它即能实现XM的功能,也提供了自动装配的功能,采用了自动装配后,程序员所需要做的决断就少了,更有利于对程序的开发,这就是约定大于配置的开发原则。
在Spring中,提供了两种方式来发现Bean:
组件扫描:通过定义资源的方式,让Spring loc容器扫描对应的包,从而把Bean装配进来。
自动装配:通过定义注解,让—些依赖关系可以通过注解完成。
2、定义一个类
@Component
@Data
public class Dog {
@Value("1")
private Integer id;
@Value("发发")
private String name;
@Value("贵宾犬")
private String breed;
}
3、测试
public class TgAnnIocTest01 {
public static void main(String[] args) {
//获取Spring上下文
ApplicationContext ctx=new AnnotationConfigApplicationContext(TgAnnIocConfig.class);
Dog dog = (Dog) ctx.getBean("dog");
System.out.println(dog);
}
}
代码分析:
1、@Component注解代表Spring会把注解修饰的类扫描成bean。这个注解的value属性就相当于我们在XML中配置的bean的id。在不指定value属性时,spring会自动为我们生成一个id,这个id就是我们的类名首字母小写
2、@Value注解代表的是注入的值,这里我们只是简单的注入了一些值。这个地方id是int类型,我们不用操心,Spring会自己知道帮我们转换的。
3、我们定义了一个类TgAnnIocConfig。这个类就相当于我们之前用过的XML配置文件,可以把它理解为Spring的一个配置类。这个类里面我们使用了一个注解@ComponentScan,这个注解代表的就是扫描当前包和子包。
4、使用了注解的方式注入bean在之后,我们开发的时候上下文用AnnotationConfigApplicationContext。
自定义扫描包按照之前讲的方式,我们定义的扫描配置只能扫描配置类对应的包和子包。但在真正的开发中,我们更多的情况是需要自定义要扫描的包的路径,这个时候如何解决呢?
@Component有一个属性叫basePackages,这个属性是一个数组,这个数组里面存放的就是我们要扫描的包的路径。只要你配置了这个属性,Spring会自动扫描你配置的包和下面的子包。
@ComponentScan(basePackages = "com/tgxit/spring/annioc/beans")
扫描多个包
@ComponentScan(basePackages = {
"com/tgxit/spring/annioc/beans",
"com/tgxit/spring/annioc/beans1",
"com/tgxit/spring/annioc/beans2",
"com/tgxit/spring/annioc/beans3"
})
自定义扫描类
我们还可以通过指定对应的类的方式来进行扫描,如果我们指定了对应的类,那么Spring会扫描对应的类所在包下面的所有类。
1、定义一个新的类Cat
@Component
@Data
public class Cat {
@Value("1")
private Integer id;
@Value("汤圆")
private String name;
@Value("美短")
private String breed;
}
2、@ComponentScan的属性basePackageClasses扫描Cat类所在包下面的所有类
@ComponentScan(basePackageClasses = Cat.class)
public class TgAnnIocConfig {
}
3、测试
public class TgAnnIocTest01 {
public static void main(String[] args) {
ApplicationContext ctx=new AnnotationConfigApplicationContext(TgAnnIocConfig.class);
Dog dog = (Dog) ctx.getBean("dog");
System.out.println(dog);
Cat cat = (Cat) ctx.getBean("cat");
System.out.println(cat);
}
}
按类型获取bean
按照之前我们学习的,我们获取类对应的id是通过id来获取的。其实Spring还给我们提供了通过类型来获取bean的方式。
public class TgAnnIocTest01 {
public static void main(String[] args) {
//获取spring的上下文
ApplicationContext ctx=new AnnotationConfigApplicationContext(TgAnnIocConfig.class);
//在ioc容器中找到对应的类型的bean,然后返回
Dog dog=ctx.getBean(Dog.class);
System.out.println(dog);
Cat cat=ctx.getBean(Cat.class);
System.out.println(cat);
}
}
自动装配
我们上面给大家介绍的Dog,Cat这些类的属性,要不是Int,要不是String。反正都是一些简单的数据类型,但是如果有一个类是复杂的数据类型的怎么办?
@Component
@Data
public class Cat {
@Value("1")
private Integer id;
@Value("汤圆")
private String name;
@Value("美短")
private String breed;
@Autowired
private Master master;
}
这里我们使用了Autowired注解。这个注解的作用是,Spring把所有的Bean都生成好了后,如果发现了有这个注解,Spring就会按这个属性的类去Spring容器里面找到找到对应的已经创建好的Bean,然后注入到这个属性中。



