一:对象,JavaBean,SpringBean的区别
1.什么是JavaBean
javaBean要求所有属性为私有,该类必须有一个公共无参构造函数,private属性必须提供公共的Getter setter给外部访问
/** * @author yzh * @date 2021/4/29 8:42 **/ public class User { //javaBean要求所有属性为私有,该类必须有一个公共无参构造函数,private属性必须提供公共的Getter setter给外部访问 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
2.什么是SpringBean
SpringBean是受Spring管理的对象,所有能受Spring管理的对象都可以是SpringBean
3.SpringBean和JAVABean的区别
- 用处不同:传统javabean更多地作为值传递参数,而spring中的bean用处几乎无处不在,任何组件都可以被称为bean
- 写法不同:传统javabean作为值对象,要求每个属性都提供getter和setter方法;但spring中的bean只需为接受设值注入的属性提供setter方法
生命周期不同:传统javabean作为值对象传递,不接受任何容器管理其生命周期;spring中的bean有spring管理其生命周期行为
二:如何定义一个SpringBean
准备工作:引入Spring依赖包
org.springframework spring-context 5.2.14.RELEASE
1.通过ClassPathXmlApplicationContext
通过ClassPathXmlApplicationContext需要指定configLocation,所有我们现在resources目录下新建一个Spring.xml文件
同时相应对象重写toString方法,便于更好观察user1和user2
package org.example.bean; /** * @author yzh * @date 2021/4/29 8:42 **/ public class User { //javaBean要求所有属性为私有,该类必须有一个公共无参构造函数,private属性必须提供公共的Getter setter给外部访问 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public User(String name) { this.name = name; } public User() { } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
运行测试类
package org.example.bean; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author yzh * @date 2021/4/29 8:45 **/ public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(); classPathXmlApplicationContext.setConfigLocation("Spring.xml"); classPathXmlApplicationContext.refresh(); User user1 = classPathXmlApplicationContext.getBean("user1",User.class); System.out.println(user1); User user2 = classPathXmlApplicationContext.getBean("user2", User.class); System.out.println(user2); } }
运行结果如下
User{name='zhangsan'}
User{name='lisi'}
2.通过AnnotationConfigApplicationContext底层
也是通过BeanDefinition实现
*@Bean@Component@Service@Controller都可以;一般@Service用于Service层,@Controller用于Controller层,此处以@Bean为例
新建一个Config类,并给User打上@Bean标签
package org.example.bean; import org.springframework.context.annotation.Bean; /** * @author yzh * @date 2021/4/29 9:20 **/ public class Config { @Bean public User user(){ return new User(); } }
通过AnnotationConfigApplicationContext获取bean,并打印bean对象
package org.example.bean; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author yzh * @date 2021/4/29 8:45 **/ public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); annotationConfigApplicationContext.register(Config.class); annotationConfigApplicationContext.refresh(); User user = annotationConfigApplicationContext.getBean("user",User.class); System.out.println(user); } }
运行结果
User{name='null'}
3.通过BeanDefinition
package org.example.bean; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author yzh * @date 2021/4/29 8:45 **/ public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); //定义一个Bean beanDefinition.setBeanClass(User.class); //把生成的Bean注册到容器中 annotationConfigApplicationContext.refresh(); annotationConfigApplicationContext.registerBeanDefinition("userTest",beanDefinition); User userTest = annotationConfigApplicationContext.getBean("userTest", User.class); System.out.println(userTest); } }
运行结果
User{name='null'}
4.通过FactoryBean
4.1通过FactoryBean与注解方式
首先新建一个Person类
package org.example.bean; import org.springframework.stereotype.Component; /** * @author yzh * @date 2021/4/29 10:00 **/ public class Person { }
然后新建一个PersonFactoryBean类,并实现FactoryBean接口,重写其方法,为其打上@component注解, 此处和在Person类上打注解是同一效果
package org.example.bean; import org.springframework.beans.factory.FactoryBean; import org.springframework.stereotype.Component; /** * @author yzh * @date 2021/4/29 10:01 **/ @Component("person") public class PersonFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { return new Person(); } @Override public Class> getObjectType() { return Person.class; } }
其次添加一个Config类打上@ComponentScan("org.example.bean"),目的是为了扫描包下的注解
package org.example.bean; import org.springframework.context.annotation.ComponentScan; /** * @author yzh * @date 2021/4/29 9:20 **/ @ComponentScan("org.example.bean") public class Config { }
最后通过AnnotationConfigApplicationContext获取Bean
package org.example.bean; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author yzh * @date 2021/4/29 8:45 **/ public class Main { public static void main(String[] args) { //Config类为包扫描配置类 AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class); Person person = annotationConfigApplicationContext.getBean("person", Person.class); System.out.println(person); } }
运行结果
org.example.bean.Person@28ac3dc3
4.2通过Factory和BeanDefinition
1.同4.1一样新建一个Person类
2.同4.1一样新建一个PersonFactoryBean类,实现FactoryBean接口,但是不打注解
3.通过BeanDefinition获取对象
此处和注解生成的差别在于通过BeanDefinition注册的会生成两个Bean对象,一个是person对应的类型是Person,另一个是&person对应的类型是PersonFactoryBean,通过下面代码的getBean方法可以看出来!!
package org.example.bean; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author yzh * @date 2021/4/29 8:45 **/ public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); ////定义一个Bean beanDefinition.setBeanClass(PersonFactoryBean.class); //把生成的Bean注册到容器中 //annotationConfigApplicationContext.refresh(); //此处会生成2个Bean对象 第一个对象为&person对应的类型的PersonFactoryBean 第二个对象为person对应的类型为Person; annotationConfigApplicationContext.registerBeanDefinition("person",beanDefinition); PersonFactoryBean personFactoryBean = annotationConfigApplicationContext.getBean("&person", PersonFactoryBean.class); System.out.println(personFactoryBean); Person person = annotationConfigApplicationContext.getBean("person", Person.class); System.out.println(person); } }
运行结果如下
org.example.bean.PersonFactoryBean@3aeaafa6
org.example.bean.Person@76a3e297
注
FactoryBean接口提供三个方法,但是我们重写了两个方法,这是因为另外一个方法是默认实现了的
FactoryBean接口方法如下:
package org.springframework.beans.factory; import org.springframework.lang.Nullable; public interface FactoryBean{ String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType"; @Nullable T getObject() throws Exception; @Nullable Class> getObjectType(); //默认实现方法,是否是单例 default boolean isSingleton() { return true; } }
5.通过Supplier
package org.example.bean; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.function.Supplier; /** * @author yzh * @date 2021/4/29 8:45 **/ public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); annotationConfigApplicationContext.refresh(); annotationConfigApplicationContext.registerBean(User.class, new Supplier() { @Override public User get() { User user = new User(); user.setName("123"); return user; } }); User user = annotationConfigApplicationContext.getBean("user", User.class); System.out.println(user); } }
bean的注入方式本文只是提供了多种api,很多情况下底层其实用的都是一样的东西,只是提供了不同的使用方式,具体可以通过源码查看。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。