IOC操作Bean管理的两种方式
- Bean管理指的是两个操作
- Spring创建对象
- Spring注入属性
Bean管理操作有两种方式
- 基于xml配置文件方式实现
- 基于注解方式实现
IOC操作Bean管理(基于xml方式)
class book{
private String bname;
private String bauthor;
public void setBname(String bname){
this.bname=bname;
}
public void setBauthor(String bauthor){
this.bauthor=bauthor;
}
public void testDemo(){
System.out.println(bname+" "+bauthor);
}
}
class test{
public static void main(String args[]){
ApplicationContext demo=new ClassPathXmlApplicationContext("src/beans.xml");
book test=demo.getBean("book",book.class);
test.testDemo();
}
}
基于xml创建对象
<bean id="book" class="src.com.xf.spring.book"></bean>
基于xml方式注入属性
<bean id="book" class="src.com.xf.spring.book">
<property name="bname" value="a coat"></property>
<property name="bauthor" value="xf"></property>
</bean>
bean管理xml注入
- 在spring配置文件中,使用bean标签,标签里添加相应属性就可以实现对象创建
- 在bean标签有很多属性,常用属性:id属性:唯一标识 class属性:类全路径
- 创建时候,默认也是执行无参数构造方法完成创建对象
基于xml方式注入属性
DI:依赖注入,就是注入属性
第一种注入方式:使用set方法进行注入(如上述例子)
第二种注入方式:使用有参构造进行注入
创建类,定义属性,创建属性对应含参构造方法
public class order {
private String name;
private String address;
public order(String name, String address) {
this.name = name;
this.address = address;
}
public void testDemo(){
System.out.println(name+" "+address);
}
}
<bean id="order" class="src.com.xf.spring.order">
<constructor-arg name="name" value="xf"></constructor-arg>
<constructor-arg index="1" value="china"></constructor-arg>
</bean>
public class testDemo {
public static void main(String args[]){
ApplicationContext demo=new ClassPathXmlApplicationContext("src/beans.xml");
order test=demo.getBean("order",order.class);
test.testDemo();
}
}
p名称空间注入
-
使用p名称空间注入,可以简化xml配置方式(用于set方法注入)
第一步 添加p名称空间在配置文件中
<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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
第二步 进行属性注入,在bean标签里进行操作
<bean id="book" class="src.com.xf.spring.book" p:bname="a coat" p:bauthor="xf"></bean>
IOC操作Bean管理(xml注入其他类型属性)
1.字面量
-
null值
<property name="address"> <null/> </property>
-
属性值包含特殊符号
转义符:< ; >
<![CDATA[<>]]>
<property name="address">
<value><![CDATA[<<China>>]]></value>
</property>
注入属性——外部bean
创建两个类service和dao类
在service调用dao里面的方法
public class Service {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("add....");
userDao.update();
}
}
public interface UserDao {
void update();
}
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("update UserDao");
}
}
在spring配置文件中进行配置
<bean id="Service" class="src.service.Service">
<property name="userDao" ref="UserDaoImpl"></property>
</bean>
<bean id="UserDaoImpl" class="src.dao.UserDaoImpl"></bean>
测试
public class testBean {
public static void main(String args[]){
ApplicationContext context=new ClassPathXmlApplicationContext("src/beans.xml");
Service demo=context.getBean("Service",Service.class);
System.out.println(demo);
demo.add();
}
}
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-haZ5XRTb-1656835094286)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220628133004700.png)]
注入属性——内部bean和级联赋值
引入:数据库一对多关系
部门department 员工employment
两实体,两个类
public class Department {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
@Override
public String toString() {
return "Department{" +
"dname='" + dname + '\'' +
'}';
}
}
public class Employee {
private String eName;
private String gender;
private Department depart;
public void seteName(String eName) {
this.eName = eName;
}
public void setGender(String gender) {
this.gender = gender;
}
public Department getDepart() {
return depart;
}
public void setDepart(Department depart) {
this.depart = depart;
}
public void test(){
System.out.println(eName+" "+gender+" "+depart);
}
}
配置bean文件(两种方式,其中一种需包含get方法)
<bean id="Employee" class="src.entity.Employee">
<property name="eName" value="zhang san"></property>
<property name="gender" value="man"></property>
<property name="depart" ref="Depart"></property>
<!-- <property name="depart.dname" value="security"></property>-->
</bean>
<bean id="Depart" class="src.entity.Department">
<property name="dname" value="technology"></property>
</bean>
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LutKeEcJ-1656835094287)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220628144542839.png)]
IOC操作Bean管理(xml注入集合属性)
常见集合类:数组、List、Map、Set
创建类(包含常见集合属性)
public class Student {
private String[] idNum;
private List<String> name;
private Map<String,String> course;
private Set<String> grade;
public void setIdNum(String[] idNum) {
this.idNum = idNum;
}
public void setName(List<String> name) {
this.name = name;
}
public void setCourse(Map<String, String> course) {
this.course = course;
}
public void setGrade(Set<String> grade) {
this.grade = grade;
}
public void test(){
System.out.println(Arrays.toString(idNum));
System.out.println(name);
System.out.println(course);
System.out.println(grade);
}
}
配置xml
<bean id="Student" class="src.entity.Student">
<property name="idNum">
<array>
<value>100321</value>
<value>103421</value>
<value>105421</value>
<value>105421</value>
</array>
</property>
<property name="name">
<list>
<value>name1</value>
<value>name2</value>
<value>name3</value>
</list>
</property>
<property name="course">
<map>
<entry key="9001" value="Java"></entry>
<entry key="9002" value="SQL"></entry>
<entry key="9003" value="web"></entry>
</map>
</property>
<property name="grade">
<set>
<value>99</value>
<value>299</value>
<value>919</value>
<value>499</value>
<value>599</value>
</set>
</property>
</bean>
运行结果
public class testBean {
public static void main(String args[]){
ApplicationContext context=new ClassPathXmlApplicationContext("src/beans.xml");
Student demo=context.getBean("Student",Student.class);
System.out.println(demo);
demo.test();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zEMklyFP-1656835094288)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220628152934505.png)]
在集合里设置对象类型
创建类course,含cname
public class Course {
private String cname;
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course{" +
"cname='" + cname + '\'' +
'}';
}
}
在student类引用List clist
public void setClist(List<Course> clist) {
this.clist = clist;
}
配置xml文件
<bean id="Student" class="src.entity.Student">
<property name="clist">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<bean id="course1" class="src.entity.Course">
<property name="cname" value="Java"></property>
</bean>
<bean id="course2" class="src.entity.Course">
<property name="cname" value="SQL"></property>
</bean>
运行结果
public void test(){
System.out.println(clist);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0yEnQMpU-1656835094288)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220628172708575.png)]
把集合注入部分提取出来
在spring配置中引入名称空间until
<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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
提取集合的取值
<util:list id="c1">
<value>Java</value>
<value>SQL</value>
</util:list>
将提取的值注入
<bean id="Name" class="src.entity.Student">
<property name="name" ref="c1"></property>
</bean>
操作
public void setName(List<String> name) {
this.name = name;
}
public void test(){
System.out.println(name);
}
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9q4SDiD7-1656835094288)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220628175312367.png)]
IOC操作Bean管理(工厂bean)
普通bean与工厂bean(FactoryBean)的区别:
- 普通bean的定义的类型就是返回的类型
- 工厂bean的定义的类型可以与返回值类型不同
工厂bean的实现方式:
1:让这个类作为工厂bean,实现接口FactoryBean
public class Factor implements FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
Course course=new Course();
course.setCname("Java");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
2:实现接口里面的方法,在实现方法中返回bean类型
public class testBean {
public static void main(String args[]){
ApplicationContext context=new ClassPathXmlApplicationContext("src/beans.xml");
Course demo=context.getBean("myBean",Course.class);
System.out.println(demo);
}
}
xml配置
<bean id="myBean" class="src.entity.Factor"></bean>
Bean作用域
1、在Spring里面,设置创建bean实例是单例还是多实例
2、在Spring里面,默认情况下,bean是单实例对象
3、如何设置单实例还是多实例
bean标签里的属性scope
单例实例与多例实例
singleton与prototype之间的区别:
- singleton声明单例实例,prototype声明多例实例
- singleton在加载配置文件时创建实例对象,prototype在加载配置文件时不创建实例对象,而是在调用XX方法时创建实例对象
xml通过bean标签中的scope属性声明(默认条件下为单例bean)
<bean id="myBean" class="src.entity.Student" scope="prototype"></bean>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ICCIkeWC-1656835094289)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220628211218258.png)]
<bean id="myBean" class="src.entity.Student" scope="singleton"></bean>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYlD6i9m-1656835094289)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220628211255581.png)]
bean的生命周期
-
通过构造器创建实例对象(无参构造)
-
为bean的属性设置值和对其他bean引用(调用set方法)
-
把bean实例传递bean后置处理的方法
-
调用bean的初始化方法(需进行配置初始化的方法)
-
把bean实例传递bean后置处理器的方法
-
bean可以使用了(对象获取到了)
-
当容器关闭时,调用bean的销毁的方法(需进行配置销毁的方法)
public class live { private String step; int i=1; public void setStep(String step) { this.step = step; System.out.println("step"+i+":setProperty"); i++; } public live() { System.out.println("Step"+i+":no_param construct"); i++; } public void Destroy_method(){ System.out.println("step"+i+":destroy"); i++; } public void Init_method(){ System.out.println("Step"+i+":InitMethod"); i++; } }
public class testBean { public static void main(String args[]){ ApplicationContext context=new ClassPathXmlApplicationContext("src/beans.xml"); live demo1=context.getBean("Live",live.class); System.out.println("step:normal use"); ((ClassPathXmlApplicationContext)context).close(); } }
配置文件
<bean id="Live" class="src.entity.live" init-method="Init_method" destroy- method="Destroy_method"> <property name="step" value="step n"></property> </bean>
IOC操作Bean管理——Bean自动装配
什么是自动装配(解决通过property引入外部类)
根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入
演示自动装配的过程
public class Dpt { @Override public String toString() { return "Dpt{}"; } } public class Emp { private Dpt dpt; private String name; public void setDpt(Dpt dpt) { this.dpt = dpt; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Emp{" + "dpt=" + dpt + ", eName='" + name + '\'' + '}'; } public void test(){ System.out.println(dpt+" "+name); } } public class testBean { public static void main(String args[]){ ApplicationContext context=new ClassPathXmlApplicationContext("src/beans.xml"); Emp demo1=context.getBean("emp",Emp.class); System.out.println(demo1); demo1.test(); } }
根据属性名称自动注入:bean标签属性autowrite,配置自动装配
autowrite属性常用两个值:
byName根据属性名称注入,注入bean的id值和类属性名称一样
<bean id="emp" class="src.autowire.Emp" autowire="byName"></bean>
通过类型名称dpt进行外部引入
byType根据属性类型注入
<bean id="emp" class="src.autowire.Emp" autowire="byType"></bean>
通过定义的dpt类型进行外部引入
IOC操作Bean管理(引入外部属性)
1、直接配置数据库信息
配置德鲁伊连接池
引入德鲁伊jar包druid
//配置连接池 <bean id="" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property> <property name="username" vlaue="root"></property> <property name="password" vlaue="root"></property> </bean>
2、引入外部属性文件数据库连接池
1、创建外部属性文件(.property),引入数据库信息
prop.driverClass=com.mysql.jdbc.Driver prop.url= prop.userName= prop.Password=
2、把外部properties属性文件引入到spring配置文件中
引入contex名称空间
在spring配置文件中使用标签引入外部属性文件 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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties" />
配置连接池
//配置连接池 <bean id=""dataSource class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${prop.driverClass}"></property> <property name="url" value="${prop.url}"></property> <property name="username" vlaue="${prop.userName}"></property> <property name="password" vlaue="${prop.password}"></property> </bean>
IOC操作Bean管理(基于注解方式实现对象创建)
什么是注解:
- 注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属 性名称=属性值)
- 使用注解,注解作用在类上面,方法上面,属性上面
- 使用注解目的:简化xml配置
2,Spring针对Bean管理中创建对象提供注解
@Component
@Service
@Controller
@Repository
四个注解功能相同,都可以用来创建bean实例
3,基于注解方式实现对象创建
第一步 引入依赖(基本依赖+spring-aop)
第二部 开启组件扫描
bean文件中引入名称空间context
扫描多个包,多个包使用逗号隔开
扫面包上层目录
<context:component-scan base-package="com.xfd.dao,com.xf.service"></context:component-scan>
第三步 创建类,在类上面添加注解
@Component(value="UserService")
public class UserService{
public void add(){
System.out.println("add.....")
}
}
在注解里面value属性值可以省略不写,默认值是类名称.首字母小写
public class Test{
public void testService(){
ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
UserService userService=context.getBean("userService",UserService.class);
userService.add();
}
}
开启组件扫描配置(哪些类需要扫描,哪些类不需要扫描)
//示例1,需要扫描的内容
<context:component-scan base-package="com.xfd.dao,com.xf.service" user-default-filter="false">
<context:include-filter type="annotion" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
//示例2,不需要扫描的内容
<context:component-scan base-package="com.xfd.dao,com.xf.service" user-default-filter="false">
<context:exclude-filter type="annotion" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
基于注解方式实现属性注入
xml配置
<context:component-scan base-package="src.service,src.dao"></context:component-scan>
1.@Autowired:根据属性类型进行自动装配
第一步 把service和dao对象创建,在service和dao类添加创建对象注解
第二步 在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解
@Repository(value = "UserDaoImpl")
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("update UserDao");
}
}
@Service
public class service {
@Autowired
public UserDaoImpl userDao;
public void add(){
System.out.println("add....");
userDao.update();
}
}
2.@Qualifler:根据属性名称进行注入,和Autowired一起使用
@Qualifler(value="userDaoImpl")
3.@Resource:可以根据 类型注入,可以根据名称注入
@Resource//根据类型注入
@Resource(name="UserDaoImpl")//根据名称进行注入
4.@Value:注入普通类型属性
public class service {
@Autowired
@Qualifier(value = "UserDaoImpl")
public UserDaoImpl userDao;
@Value(value = "abc")
private String name;
public void add(){
System.out.println("add...."+name);
userDao.update();
}
}
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wqSt75yB-1656835094290)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220703152907956.png)]
完全注解开发
创建配置类,替代xml文件(SpringConfig.java)
编写测试类
@Configuration
@ComponentScan(basePackages={"src"})
public class SpringConfig{
}
class test{
public static void main(String args[]){
ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
service demo1=context.getBean("service",service.class);
System.out.println(demo1);
demo1.add();
}
}
称注入
@Resource//根据类型注入
@Resource(name="UserDaoImpl")//根据名称进行注入
4.@Value:注入普通类型属性
public class service {
@Autowired
@Qualifier(value = "UserDaoImpl")
public UserDaoImpl userDao;
@Value(value = "abc")
private String name;
public void add(){
System.out.println("add...."+name);
userDao.update();
}
}
输出结果
[外链图片转存中…(img-wqSt75yB-1656835094290)]
完全注解开发
创建配置类,替代xml文件(SpringConfig.java)
编写测试类
@Configuration
@ComponentScan(basePackages={"src"})
public class SpringConfig{
}
class test{
public static void main(String args[]){
ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
service demo1=context.getBean("service",service.class);
System.out.println(demo1);
demo1.add();
}
}