1.IOC操作Bean管理(FactoryBean)
普通Bean:在配置文件中定义的类型就是返回的类型
工厂bean:在配置文件中定义的类型可以不是不是返回的类型
工厂bean实现FactoryBean接口即可
public class MyBean implements FactoryBean<Course> {
//定义返回对象类型
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setcName("factorybean");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
<bean id="myBean" class="com.jcy.spring5.collection.factorybean.MyBean">
</bean>
通过factorybean来配置bean的实例,但是实际返回的是实例确实是factorybean的getobject()方法返回的实例
2.bean的作用域(单例/多例)
几种作用域中,request、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。
Singleton
当一个bean的作用域为Singleton,那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。
在加载配置文件时就创建了实例对象
<bean id="user" class="com.jh.domain.User" scope="singleton"/>
Prototype
表示一个bean定义对应多个对象实例,Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。
Prototype是原型类型,它在我们创建容器的时候没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。
<bean id="user" class="com.jh.domain.User" scope="prototype" />
Request
当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;
即每一个HTTP请求,都会单独创建一个bean
,若请求结束,bean
也会随之销毁。
使用request
作用域一般不会存在线程安全问题,因为在Web
应用中,每个请求都是由一个单独的线程进行处理,所有线程之间并不会共享bean
,从而不会存在线程安全的问题。
如果使用的是注解扫描配置bean
,那么在bean
所属的类上使用@RequestScope
注解即可使用此作用域,若是基于xml
文件,则通过bean
的scope
配置项:
<bean id="loginAction" class="com.something.LoginAction" scope="request"/>
Session
Session
作用域将bean的使用范围一次在一次http会话
中,对于每一个会话,Spring容器都会创建一个单独的bean
,若Session被销毁,则bean也随之销毁。
<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>
Application
Spring 容器通过为整个 Web 应用程序使用一次 bean 定义来创建 bean 的新实例。也就是说,bean 在级别上进行范围范围存储,并存储为常规属性。
这与 Spring Singleton Bean
有些类似,但在两个重要方面有所不同:它是每个的单元,而不是每个 Spring"应用程序上下文"(对于它,在任何给定的 Web 应用程序中可能有多个),它实际上是公开的,因此作为属性可见。
application
作用域也只能用于web
应用中。使用方式和之前几种类似,可以通过@ApplicationScope
注解,也可以使用xml
配置文件:
<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>
3.Bean的生命周期
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(4) bean 可以使用了(对象获取到了)
(5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
public void testdemo4(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("获取bean实例-----4");
System.out.println(orders);
context.close();
}
//结果
//无参构造创建bean----1
//set方法设置属性值-----2
//执行初始化方法-----3
//获取bean实例-----4
//Orders{oName='iqooneo5'}
//销毁bean实例-----5
public void initMethod(){
System.out.println("执行初始化方法-----3");
}
public void destoryMethod(){
System.out.println("销毁bean实例-----5");
}
public Orders() {
System.out.println("无参构造创建bean----1");
}
public void setoName(String oName) {
this.oName = oName;
System.out.println("set方法设置属性值-----2");
}
</bean>
<bean id="orders" class="com.jcy.spring5.collection.factorybean.Orders" init-method="initMethod" destroy-method="destoryMethod">
<property name="oName" value="iqooneo5">
</property>
</bean>
Spring当中的后置处理器是Spring体用的一个扩展点,开发者只要去实现,Spring当中的BeanPostProcessor接口,那么就能插手SpringBean实例化的一个过程
BeanPostProcessor 接口也被称为后置处理器,通过该接口可以自定义调用Bean初始化前后执行的操作方法。
如果我们希望容器中创建的每一个bean
,在创建的过程中可以执行一些自定义的逻辑,那么我们就可以编写一个类,并让他实现 **BeanPostProcessor**
接口,然后将这个类注册到一个容器中。
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
4.自动装配
手动装配是通过value标签装入属性值,自己配置
<bean id="orders" class="com.jcy.spring5.collection.factorybean.Orders" init-method="initMethod" destroy-method="destoryMethod">
<property name="oName" value="iqooneo5">
</property>
</bean>
**自动装配:**Spring根据指定装配规则(属性名称或者属性类型), Spring 自动将匹配的属性值进行注入
<bean id="emp" class="com.jcy.spring5.autowire.Emp" autowire="byName">
<!-- <property name="dept" ref="dept"></property>-->
</bean>
<bean id="emp" class="com.jcy.spring5.autowire.Emp" autowire="byType">
</bean>
5.引入外部属性文件
1、直接配置数据库信息,配置德鲁伊连接池
<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" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
prop.driverClass=com.mysql.cj.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=123456
IOC 操作 Bean 管理(基于注解方式)
Spring 针对 Bean 管理中创建对象提供注解:注解可以简化xml配置
(1) @Component:把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
(2) @Service:服务(注入dao)
(3) @Controller:控制器(注入服务)
(4) @Repository:dao(实现dao访问)
上面四个注解功能是一样的,都可以用来创建 bean 实例
开启组件扫描:指明扫描包的名称
<context:component-scan base-package="com.jcy.spring5.annocation">
</context:component-scan>
//创建了bean实例
//value不加的话默认是类名首字母小写
@Component(value = "userService")
//@Service
public class UserService {
public void add(){
System.out.println("add-----");
}
}
@Test
public void testDenmo1(){
ApplicationContext context=new ClassPathXmlApplicationContext("bean5.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
System.out.println(userService);
}
//add-----
//com.jcy.spring5.annocation.service.UserService@544fa968
开启组件扫描细节配置:开启组件扫描之后不配置默认会扫描包中所有的注解
<!--示例 1
use-default-filters="false" 表示现在不使用默认 filter,自己配置 filter
context:include-filter ,设置扫描哪些内容,下面只扫描Controller
-->
<context:component-scan base-package="com.jcy" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例 2
下面配置扫描包所有内容
context:exclude-filter: 设置哪些内容不进行扫描
下面就是不扫描controller
-->
<context:component-scan base-package="com.jcy">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
基于注解方式属性注入
@Autowired:**根据属性类型(byType)**进行自动装配
第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解
第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
@Qualifier:根据名称(byname)进行注入
这个@Qualifier 注解的使用,和上面@Autowired 一起使用
@Service
public class UserService {
@Autowired
@Qualifier(value = "userDaoImpl")
private UserDao userDao;
public void add(){
System.out.println("add-----");
userDao.add();
}
}
@Repository
public class UserDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("dao add======");
}
}
@Resource:可以根据类型注入,可以根据名称注入,就类似与autowire和qualifier二者的替代品
@Resource
@Resource(name = "userDaoImpl")
@Value:注入普通类型属性
前三者针对对象类型的注入,而value针对普通类型的注入
纯注解开发
用配置类替代xml配置文件
@Configuration
@ComponentScan(basePackages = "com.jcy")
public class SpringConfig {
}
@Test
public void testDemo01(){
ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.add();
System.out.println(userService);
}