Spring Bean
bean是什么? 我们可以将Spring的Bean理解为在Spring框架下的对象。
基于xml的实现
bean标签里配置的是需要spring框架管理的类
bean标签里面都可以写 id :生成对象的名字,是唯一的
class:全类名(就是地址)
name:对象的别名,可以是多个
scope:范围,作用域 ● singleton :单例,也是默认的,在容器中只讲对象创建一个,多次获取时也只是同一个,在Spring启动时就创建好了 ● prototype :原型(多例),单个bean定义可以绑定到多个对象实例。 就是get一次,就创建一个对象。 ● request:单个bean定义被绑定到当Http请求的生命周期上。就是每一次Http请求都是有属于自己的单独实例创建。仅用于 WebApplicationContext 环境 就是一个请求创建一个对象。 ● session:单个bean的定义会绑定到Http Session的生命周期上。仅用于 WebApplicationContext 环境 一个会话,就创建一个对象。同一个 http session 共享一个 Bean, 不同 Session 使用不同的 Bean。 ● application:带个bean的定义会绑定到 ServletContext的生命周期上。仅用于 WebApplicationContext 环境 整个应用程序只有这一个对象。 ● websocket:单个bean的定义会绑定到WebSocket的生命周期中。仅用于 WebApplicationContext 环境 整个服务器中就创建一个对象。
代码演示:
package com.demo.spring.model;
public class User {
private String name;
private Integer age;
public User(){
System.out.println("这是User的无参构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
name定义别名的演示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" name="user1,user2" class="com.demo.spring.model.User"></bean>
</beans>
测试代码
package com.demo.spring.test;
import com.demo.spring.model.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Object user = applicationContext.getBean("user");
User user1 = (User) applicationContext.getBean("user1");
User user2 = applicationContext.getBean("user2", User.class);
System.out.println(user);
System.out.println(user1);
System.out.println(user2);
}
}
通过name定义的别名都是可以调用到定义的bean标签。
scope作用域的演示
singleton 演示
在xml中的bean标签里加上scope="singleton"再执行测试代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" name="user1,user2" class="com.demo.spring.model.User" scope="singleton"></bean>
</beans>
在将测设代码,通过debug调试可以体现出singleton是在创建Spring时就创建好了对象。 它只是创建了一个对象,每次拿到的是同一对象
prototype 演示
在xml中的bean标签里加上scope="prototype"再执行测试代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" name="user1,user2" class="com.demo.spring.model.User" scope="prototype"></bean>
</beans>
走测试代码,就可以明显的看出,它创建出了三个对象
xml配置方式的依赖注入(创建对象,为对象中的值赋值)
典型的企业级应用程序不会只有一个对象的(值Spring中的bean)。即使最简单的应用程序也有一些对象是一起工作的,最终传送到达前端的。
依赖项注入(DI:Dependency Injection)是指:对象仅仅通过构造函数的参数,工厂方法的参数或从工厂方法构造,或返回对象实例后在其上设置属性来定义依赖项(即它们使用的其他对象)。然后容器在创建bean时注入这些依赖项。这个过程基本上和bean通过直接类的构造器或服务定位器来定位其依赖的过程是相反的。(因此也称为了控制反转)
依赖(DI)和IOC可以说是同时存在的 IOC是在创建Spring的对象,DI是为依赖注入,为创建好的对象属性注入值。
依赖注入就是在Spring创建对象的时候,将对象的属性注入进去(就是赋值) 注入的方式有两种:
- 通过构造方法进行注入(采用这种的方式是比较少的)
- 通过set的方法进行注入
package com.demo.spring.model;
import java.util.List;
public class User {
private String name;
private Integer age;
private List<Integer> list;
public User() {
System.out.println("这是User的无参构造方法");
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("这是setName的方法");
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("这是setAge的方法");
this.age = age;
}
public List<Integer> getList() {
return list;
}
public void setList(List<Integer> list) {
this.list = list;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", list=" + list +
'}';
}
}
Test1类进行代码的测试验证
package com.demo.spring.test;
import com.demo.spring.model.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
}
方式一:通过构造方式的注入属性值
在constructor-arg中 name是采用的是定义的赋值,type是值的是对象属性的数据类型,在采用属性的数据类型的时候如果是引用型的话,应该用去全类名(例如:java.lang.String。java.lang.Integer)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.demo.spring.model.User">
<constructor-arg name="name" value="Jim"></constructor-arg>
<constructor-arg type="java.lang.Integer" value="15"></constructor-arg>
</bean>
</beans>
方式二:通过set的方式注入属性的值
就是通过属性的名字将第一个字母大写拼上set构成以set的方式进行注入。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.demo.spring.model.User">
<property name="name" value="Dark"></property>
<property name="age" value="20"></property>
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>
</beans>
其他具体的可以结合官网的信息进行参考查询
set注入时用的ref (指向的是引用于另一个对象的使用)
这样就使得代码之间的依赖度更低,代码直接的关联也更加的方便。 这样在类中我们就可以不用去new对象,只需要标注一个对象类型的属性就可以了
package com.demo.spring.dao;
public class UserDao {
public void save() {
System.out.println("这是UserDao中的save方法");
}
}
在这里通过在Spring的注入将UserDao赋给UserService中的userDao属性
然后在UserService中的直接使用
package com.demo.spring.service;
import com.demo.spring.dao.UserDao;
public class UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void saveUser() {
System.out.println("这是UserService中的saveUser中的方法");
userDao.save();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.demo.spring.dao.UserDao"></bean>
<bean id="userService" class="com.demo.spring.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
package com.demo.spring.test;
import com.demo.spring.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test2 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = applicationContext.getBean("userService",UserService.class);
userService.saveUser();
}
}
执行结构如下:
用注解的方式进行依赖注入(主流方式)
注解是在2.5之后出现的 因为我们在写一个项目的时候,如果要创建300个对象,那么我们就要写600个bean,实在是太麻烦了,所以出现了注解,就是为了方便。
那注解是不是就比xml更好呢? 每种方法都有其优缺点,通常情况下,是由开发人员决定哪种策略更适合它们。由于它们的定义方式,注解在其声明中提供了大量上下文,从而导致配置更简短。 然而,XML擅长在不接触源代码或重新编译组件的情况下注入组件。一些开发人员更喜欢将注入靠近源代码,而其他人则认为带注解的类不再POJO,而且配置变得分散且难以控制。 无论选择哪一种,Spring都能容纳这两种风格,甚至可以将它们混合在一起。
注解功能是封装在AOP包当中,我们只要导入Spring aop jar包即可,在用maven结构时,我们在导入spring包时,就已经在依赖的关系下,工具已经帮我们导入了aop包。 接下来在Spring的配置文件中加这个配置
注解创建对象
● @Component(value=“user”) 等同于< bean id=“user” class=“ ” >< /bean > 就是简答的组件,一般用在model类上用这个 ● @Service ● @Repository 数据访问层 这三个标签的意思为都等同于< bean id=“user” class=“ ” >< /bean > 以上这些注解都可以实现创建对象功能,功能都是一样的。 只是为了后续扩展功能,用于区分而在不同的层使用不同的注解标记。
scope作用域的注解标签的添加
● @Scope(value=“prototype”) 原型 ● @Scope(value=“ singleton ”) 单例
注解方式注入属性[DI:Dependency Injection]
@Autowired
@Autowired 是 Spring 提供的注解,是可以写在属性和 setter 方法上,也可以写在构造方法上。如果写在属性上,那么就不需要再写 setter 方法。默认情况下它要求依赖对象必须存在, 不能为null。 如果允许 null 值,可以设置它的 required 属性为 false。比如这样设置@Autowired(required = false)
再属性上直接添加
@Autowired
private UserDao userDao;
在setter方法上添加
public UserDao getUserDao() {
return userDao;
}
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
在构造方法上添加
@Autowired
public UserService(UserDao userDao) {
this.userDao = userDao;
}
byType自动注入
@Autowired默认是根据属性的类型进行自动注入(根据属性的类型在Spring的容器进行查找)
byName自动注入
如果我们想要根据名字去查找的话,就要结合@Qualifier 注解一起来使用。 @Qualifier (value = “名字”)
需要在引用属性上联合使用注解@Autowired 与@Qualifier一起来使用。@Qualifier 的 value 属性值是用于指定要匹配的 Bean 的 id 值。
代码演示
spring配置文件中只需要开启注解扫描就可以了
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.demo.spring"></context:component-scan>
</beans>
package com.demo.spring.model;
import org.springframework.stereotype.Component;
import java.util.List;
@Component(value = "user")
@Scope(value = "singleton")
public class User {
private String name;
private Integer age;
private List<Integer> list;
public User() {
System.out.println("这是User的无参构造方法");
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("这是setName的方法");
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("这是setAge的方法");
this.age = age;
}
public List<Integer> getList() {
return list;
}
public void setList(List<Integer> list) {
this.list = list;
}
}
package com.demo.spring.dao;
import org.springframework.stereotype.Repository;
@Repository(value = "userDao")
public class UserDao {
public void save() {
System.out.println("这是UserDao中的save方法");
}
}
根据值的属性进行赋值
package com.demo.spring.service;
import com.demo.spring.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service(value = "userService")
public class UserService {
@Autowired
private UserDao userDao;
public void saveUser() {
System.out.println("这是UserService中的saveUser中的方法");
userDao.save();
}
}
测试代码
package com.demo.spring.test;
import com.demo.spring.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test2 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = applicationContext.getBean("userService",UserService.class);
userService.saveUser();
}
}
2.根据getName来注入值
package com.demo.spring.service;
import com.demo.spring.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service(value = "userService")
public class UserService {
@Autowired
@Qualifier(value = "userDao")
private UserDao userDao;
public void saveUser() {
System.out.println("这是UserService中的saveUser中的方法");
userDao.save();
}
}
@Resource
@Resource是jdk提供的注解用于自动注入 在Spring中也提供了对jdk中@Resource注解标签的支持。 @Resource 注解既可以按名称匹配 Bean,也可以按类型匹配 Bean。
@Resource(name = “userDao”)中name = "userDao"指定注入的对象名,比@Autowired比较,在通过name名查询的话,它只需要一行就可以了。 如果不加的话就按照数据类型来注入。
代码演示
通过byName注入
package com.demo.spring.service;
import com.demo.spring.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service(value = "userService")
public class UserService {
@Resource(name = "userDao")
private UserDao userDao;
public void saveUser() {
System.out.println("这是UserService中的saveUser中的方法");
userDao.save();
}
}
运行Test方法
package com.demo.spring.test;
import com.demo.spring.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test2 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = applicationContext.getBean("userService",UserService.class);
userService.saveUser();
}
}
是可以执行的 通过byType注入
package com.demo.spring.service;
import com.demo.spring.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service(value = "userService")
public class UserService {
@Resource
private UserDao userDao;
public void saveUser() {
System.out.println("这是UserService中的saveUser中的方法");
userDao.save();
}
}
xml与注解的对比
xml
● 优点是:配置和代码是分离的,在 xml 中做修改,无需编译代码,只需重 启服务器即可将新的配置加载。 ● 缺点是:编写麻烦,效率低,大型项目过于复杂。
注解
● 优点:方便,直观,高效(代码少,没有配置文件的书写那么复杂)。 ● 缺点:以硬编码的方式写入到 Java 代码中,修改后是需要重新编译代码的。
|