黑马教学视频链接 https://www.bilibili.com/video/BV1rt4y1u7q5
BeanFactorty版本的快速入门
导入spring坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.7</version>
</dependency>
通过测试类获取Bean(IoC)
test类
package com.tansor.test;
import com.tansor.service.UserService;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
public class BeanFactoryTest {
public static void main(String[] args) {
//创建工厂对象
DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
//创建读取器
XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(beanFactory);
//读取器配置文件给工厂
reader.loadBeanDefinitions("beans.xml");
//根据id获取Bean实例对象
UserService userService = (UserService) beanFactory.getBean("userService");
//获取对象信息
System.out.println(userService);
}
}
beans.xml
<?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="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>
<!--id为bean识别信息,class为类的路径-->
</beans>
Bean的注入(DI注入)
如下,UserService需要一个UserDao对象,故注入
package com.tansor.service.impl;
import com.tansor.dao.UserDao;
import com.tansor.service.UserService;
public class UserServiceImpl implements UserService {
public UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
}
beans.xml
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property><!--将userDao的bean注入-->
<!--此处name对应userService类中的set方法,如果是方法名称为setUserDao,那么此处userDao,如果是setXyzAbc,那么此处xyzAbc(去掉set首字母大写)-->
<!--此处ref指的是注入的对象是哪个,写上那个bean的id(此处为userDao)-->
</bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
</beans>
ApplicationContext快速入门
IoC
package com.tansor.test;
import com.tansor.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext();
//ClassPathXmlApplicationContext()直接从resources资源文件夹读取
//FileSystemXmlApplicationContext()从系统目录路径
//AnnotationConfigApplicationContext()从注解配置类加载配置文件
//以上三种只针对基础spring环境
UserService userService= (UserService) applicationContext.getBean("beans.xml");
}
}
//BeanFactory直到getBean这一步才会创建Bean
//ApplicationContext加载配置文件后就创建了Bean
基于xml的spring应用
springBean的配置详解
xml配置方式 | 功能描述 |
---|---|
<bean id=""> |
bean的id和全限定名配置,通过别名也能获取到Bean |
<bean name=""> |
通过name设置Bean别名, |
<bean scope=""> |
Bean作用范围,BeanFactory作为容器时取值singleton和prototype |
<bean lazy-init=""> |
Bean的实例化时机,是否延迟加载,BeanFactory作为容器时无效 |
<bean init-method=""> |
Bean实例化后自动执行的方法,method指定方法名 |
<bean destory-method=""> |
Bean实例销毁前的方法 |
<bean autowire="byType"> |
设置自动注入模式,常用的有 1.按照类型——byType 2.按照名字——byName |
<bean factory-bean="" factory-method=""/> |
指定哪个工厂Bean的哪个方法完成Bean的创建 |
BeanName
beanName有多种形成方式(绝大多数都只用id,name一辈子也用不到几次,白雪白雪)
- 不写id,不写name,beanName为bean中类名的完整引用路径(例如com.tansor.userService.impl.UserServiceImpl)
- 写id,不写name,beanName为bean标记中指定的id,此时不允许用完整引用路径去getBean
- 写id,写name,beanName为bean标记中指定的id,但是可以通过id或者name去getBean(aliasMap别名映射,将别名映射到id,别名可以写多个,比如id=”aaa,bbb,ccc”)
- 不写id,写name,此时beanName从name得到,如果只有一个name那就是name,如果有多个name那就是第一个name作为beanName
Bean的作用范围scope配置
基础spring环境下Bean的作用范围(一般都是singleton)
-
singleton
单例,spring容器创建的时候就会进行实例化,存到单例池(一级缓存),每次getBean都是一样的
-
prototype
原型,只有getBean时才会创建Bean实例,每次都会创建一个新的实例,不会存进单例池
spring-webmvc
多出来两种scope
- request
- session
N级缓存是什么
- 三级缓存:最底层的缓存,用来存放一个Bean工厂对象,该工厂对象负责生成Bean的代理对象。当检测到循环依赖时,Spring会通过这个工厂对象提前暴露一个Bean的代理对象,以此打破循环依赖
singletonFactories
。 - 二级缓存:存放的是提前暴露的、但尚未完全初始化完成的Bean对象(即完成了实例化和部分属性注入,但还未进行初始化方法调用)。这个缓存的存在是为了解决A依赖B,B依赖A这样的场景,在A创建的过程中需要B,而B又依赖于A,这时可以从二级缓存中获取到提前暴露的B的引用,从而解决循环依赖的问题
earlySingletonObject
。 - 一级缓存:存放完全初始化好的Bean,单例池
singletonObject
。
Bean延迟加载(对BeanFatory无效)
lazy-init为true时等到你使用getBean才会创建Bean并存储到单例池,否则spring容器一创建就会创建它
init-method
该方法在对象实例化之后执行
destroy-method
必须显式的关闭才会调用,例如applicationContext.close()
InitializingBean
使业务类实现InitializingBean
接口,并实现afterPropertiesSet()
方法
实例化之后执行属性设置(DI注入),然后执行本方法,然后再执行init-method
Bean有参构造
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<constructor-arg name="userDao1" value="userDao"></constructor-arg><!--UserService的构造函数的第一个参数,name是参数名,value对应参数值的bean的id-->
<constructor-arg name="userDao2" value="userDao"></constructor-arg><!--构造函数的第一个参数,要几个参数创建几个constructor-arg标签-->
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
</beans>
静态工厂
package com.tansor.factory;
import com.tansor.dao.UserDao;
import com.tansor.dao.impl.UserDaoImpl;
public class MyBeanFactory1 {
public static UserDao userDao(){
return new UserDaoImpl();
}
}
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<constructor-arg name="userDao1" value="userDao"></constructor-arg>
<constructor-arg name="userDao2" value="userDao"></constructor-arg>
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="userDao1" class="com.tansor.factory.MyBeanFactory1" factory-method="userDao">
<!--如果userDao()有参数就增加<constructor-arg>来增加参数-->
</bean>
<!--调用MyBeanFactory1中的方法userDao(factory-method),然后把返回的对象实例作为userDao1-->
</beans>
实例工厂(非静态工厂方式)
package com.tansor.factory;
import com.tansor.dao.UserDao;
import com.tansor.dao.impl.UserDaoImpl;
public class MyBeanFactory2 {
public UserDao userDao(){
return new UserDaoImpl();
}
}
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<constructor-arg name="userDao1" value="userDao"></constructor-arg>
<constructor-arg name="userDao2" value="userDao"></constructor-arg>
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="beanFactory2" class="com.tansor.factory.MyBeanFactory2"></bean>
<!--实例化一个bean-->
<bean id="userDao2" factory-bean="beanFactory2" factory-method="userDao">
<!--如果userDao()有参数就增加<constructor-arg>来增加参数-->
</bean>
<!--用刚才实例化的bean作为factory-bean,调用其中的userDao(),获取返回的UserDao作为MyBeanFactory2-->
</beans>
实现FactoryBean规范延迟Bean实例化
package com.tansor.factory;
import com.tansor.dao.UserDao;
import com.tansor.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;
public class MyBeanFactory3 implements FactoryBean<UserDao> {
//继承FactoryBean
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
@Override
public Class<?> getObjectType() {
return UserDao.class;
}
}
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<constructor-arg name="userDao1" value="userDao"></constructor-arg>
<constructor-arg name="userDao2" value="userDao"></constructor-arg>
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="userDao3" class="com.tansor.factory.MyBeanFactory3"></bean>
<!--返回的是MyBeanFactory3使用getObject()返回的对象实例-->
<!--单例池中userDao3对应的其实是MyBeanFactory3,只有当测试类中getBean被执行时,才会生成真正的返回的对象userDao3存储在factoryBeanObjectCache中-->
</beans>
注入方式和注入数据类型(手动装配)
通过set方法注入
- 普通数据类型
例如String ,int,boolean等
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<property name="userName" ref="xiaoming"></property><!--普通属性值注入使用value,此时UserServiceImpl中有方法setUserName()-->
</bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
</beans>
- 引用数据类型
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property><!--引用注入使用ref,此时UserServiceImpl中有方法setUserDao()-->
</bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
</beans>
- 集合数据类型
<?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="userService" class="com.tansor.service.impl.UserServiceImpl">
<property name="stringList">
<list><!--是List类型写List,是Set就写Set,是-->
<value>aaa</value><!--普通属性值直接往里写-->
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="userDaoList">
<list>
<ref bean="userDao1"></ref><!--引用外面的bean-->
<ref bean="userDao2"></ref>
<bean class="com.tansor.dao.impl.UserDaoImpl"></bean><!--也可以直接配一些bean-->
</list>
</property>
<property name="userDaoMap">
<map>
<entry key="key1" value="value1"></entry><!--普通类型的变量注入直接key-value-->
<entry key="key1" value-ref="userDao1"></entry><!--引用对象实例的变量注入直接key-value-ref-->
</map>
</property>
<property name="userDaoMap">
<props><!--Properties类型的注入-->
<prop key="prop1">value1在此</prop>
<prop key="prop2">value2在此</prop>
</props>
</property>
</bean>
<bean id="userDao1" class="com.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="userDao2" class="com.tansor.dao.impl.UserDaoImpl"></bean>
</beans>
通过构造方法注入
<property name="userName" ref="xiaoming"></property>
中的 property
换成 constructor-arg
自动装配
根据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="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>
<!--autowire为byName时,会自动检测UserServiceImpl中的set函数,去掉set首字母大写,并在寻找id与这个相同的bean进行导入-->
</beans>
根据type进行自动装配
<?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="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byType"></bean>
<!--autowire为byName时,会自动检测UserServiceImpl中的set函数中参数的类型,并在寻找类型与这个相同的bean进行导入,如果相同类型bean数量对不上参数表中数量编译器就会报错-->
<bean id="userDao1" class="com.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="userDao2" class="com.tansor.dao.impl.UserDaoImpl"></bean>
</beans>
黑马《黑马程序员新版Spring零基础入门到精通,一套搞定spring全套视频教程(含实战源码)》P26-P30不看了太麻烦了
getBean三种API
方法定义 | 返回的值和参数 |
---|---|
Object getBean(String beanName) | 返回为Object,需要强行转换类型 |
T getBean(Class Type) | 当beans中这种类型的bean只存在一个时可以用,否则不行 |
T getBean(String beanName,Class type) | 肥肠好,指定classtype使用UserService.class |
Spring导入非自定义Bean
现在Maven导入jdbc和alibaba数据源坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring_test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
</dependencies>
</project>
bean配置文件中导入
<?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="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>
<bean class="com.alibaba.druid.pool.DruidDataSource">
<property name="name" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_db"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
导入mysql的Connection
<?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="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>
<bean id="aClass" class="java.lang.Class" factory-method="forName">
<constructor-arg name="className" value="com.mysql.jdbc.Driver"></constructor-arg>
</bean>
<bean id="connection" class="java.sql.DriverManager" factory-method="getConnection">
<constructor-arg name="url" value="com.mysql.jdbc.Driver"></constructor-arg>
<constructor-arg name="user" value="root"></constructor-arg>
<constructor-arg name="password" value="root"></constructor-arg>
</bean>
<!--对应以下语句
Class.forName("com.mysql.jdbc.Driver");
Connection connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis_db","root","root");
-->
</beans>
时间转化为标准格式并获取Date对象
<?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="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>
<bean id="simpleDateFormat" class="java.text.SimpleDateFormat" scope="prototype">
<constructor-arg name="pattern" value="yyyy-MM-dd HH:mm:ss"></constructor-arg>
</bean>
<!--对应SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");-->
<bean id="date" factory-bean="simpleDateFormat" factory-method="parse">
<constructor-arg name="source" value="2024-03-08 21:56:00"></constructor-arg>
</bean>
<!--对应Date date=simpleDateFormat.parse(currentTimeStr);-->
</beans>
package com.tansor.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
System.out.println(applicationContext.getBean("date"));
}
}
配置sqlSessionFactory(MyBatis)
导入maven坐标
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
在resource目录下新建mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
传统做法
测试类
package com.tansor.test;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class ApplicationContextTest {
public static void main(String[] args) throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory=builder.build(in);
}
}
白雪做法(配个Bean)
<?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="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>
<!-- InputStream in = Resources.getResourceAsStream("mybatis-config.xml");-->
<!-- SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();-->
<!-- SqlSessionFactory sqlSessionFactory=builder.build(in);-->
<bean id="inputStream" class="org.apache.ibatis.io.Resources" factory-method="getResourceAsStream">
<constructor-arg name="resource" value="mybatis-config.xml"></constructor-arg>
</bean>
<bean id="builder" class="org.apache.ibatis.session.SqlSessionFactoryBuilder"></bean>
<bean id="sessionFactory" factory-bean="builder" factory-method="build">
<constructor-arg name="inputStream" ref="inputStream"></constructor-arg><!--注意此处ref-->
</bean>
</beans>
BeanDefinition(Bean的实例化基本流程)
Spring容器在进行初始化时,一个Bean信息存储到一个BeanDefinition对象中,很多的BeanDefinition对象都存储在beanDefinitionMap集合(位于BeanFactory中)中,Spring框架在对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储在一个名为singletonObjects
的Map集合中,当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回。
BeanDefinitionMap中存的不是Bean的对象,存的仅仅是Bean的配置
Bean工厂后处理器BeanFactoryProcessor
新建一个类MyBeanFactoryPostProcessor
实现接口BeanFactoryPostProcessor
,并实现方法postProcessBeanFactory
,此方法中的参数(configurableListableBeanFactory
)存储的就是BeanDefinitionMap
,通过一下手段可以修改某些Bean的配置参数
package com.tansor.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("BeanDefinitionMap完毕后自动回调此方法");
// 获取名为userDao的Bean
BeanDefinition userDao = configurableListableBeanFactory.getBeanDefinition("userDao");
// 将这个Bean的类名改为UserServiceImpl,实现偷天换日
userDao.setBeanClassName("com.tansor.service.impl.UserServiceImpl");
}
}
bean配置文件如下
<?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 class="com.tansor.processor.MyBeanFactoryPostProcessor"></bean>
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>
</beans>
动态注册BeanDefinition(没用,白雪)
第一种,向上转型进行注册
package com.tansor.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("BeanDefinitionMap完毕后自动回调此方法");
BeanDefinition beanDefinition=new RootBeanDefinition();//创建一个新的BeanDefinition对象
beanDefinition.setBeanClassName("com.tansor.dao.impl.PersonDaoImpl");//设置Bean的参数配置
DefaultListableBeanFactory defaultListableBeanFactory=(DefaultListableBeanFactory) configurableListableBeanFactory;//将参数向上转型,以获得更多API
defaultListableBeanFactory.registerBeanDefinition("personDao",beanDefinition);//注册新的Bean
}
}
package com.tansor.test;
import com.tansor.dao.PersonDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("ApplicationContext.xml");
Object userDao = applicationContext.getBean(PersonDao.class);
System.out.println(userDao);
}
}
<?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 class="com.tansor.processor.MyBeanFactoryPostProcessor"></bean>
<!--后处理器配置在配置文件-->
<bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>
</beans>
第二种,实现子接口进行注册
新建一个类MyBeanDefinitionRegisterPostProcessor
实现接口BeanDefinitionRegistryPostProcessor
,并实现方法注册方法
package com.tansor.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
public class MyBeanDefinitionRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
BeanDefinition beanDefinition=new RootBeanDefinition();
beanDefinition.setBeanClassName("com.tansor.dao.impl.PersonDaoImpl");
beanDefinitionRegistry.registerBeanDefinition("personDao",beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
<?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.tansor.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>
<bean class="com.tansor.processor.MyBeanDefinitionRegisterPostProcessor"></bean>
<!--后处理器配置在配置文件-->
</beans>
加载properties文件
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/beans/spring-context.xsd
">
<!--开启context命名空间 ^ -->
<!--使用context空间加载properties文件-->
<context:property-placeholder location="jdbc.properties" />
<!--使用属性占位符${}获取文件内容-->
<bean class="com.alibaba.druid.pool.DruidDataSource">
<property name="name" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
</beans>
注解自动扫描
package com.tansor.dao.impl;
import com.tansor.dao.UserDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
@Controller//表现层
@Component
@Service//业务层
@Repository//数据层
public class UserDaoImpl implements UserDao {
}
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="com.tansor" />
<!--注解扫描范围定义,可以同时扫多个包-->
</beans>
纯注解开发模式
新建一个类SpringConfig
package com.tansor.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"com.tansor","com.tansor2"})//可以写好几个,写好几个需要在外面加{}
public class SpringConfig {
}
import com.tansor.config.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
//加载注解类配置
public class AppForAnnotation {
ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);
}
注解开发模式下bean生命周期
设置单例模式
package com.tansor.dao.impl;
import com.tansor.dao.UserDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@Repository
@Scope("singleton")//单例
public class UserDaoImpl implements UserDao {
}
设置原型模式
package com.tansor.dao.impl;
import com.tansor.dao.UserDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Repository
@Scope("prototype")//原型模式
public class UserDaoImpl implements UserDao {
@PostConstruct
public void init(){
System.out.println("初始化后执行");
}
@PreDestroy
public void destroy(){
System.out.println("销毁前执行");
}
}
纯注解开发依赖注入(自动装配)
package com.tansor.dao.impl;
import com.tansor.dao.UserDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Repository("userDao") //指定bean的name
@Scope("prototype")
public class UserDaoImpl implements UserDao {
@PostConstruct
public void init(){
System.out.println("初始化后");
}
@PreDestroy
public void destroy(){
System.out.println("销毁前");
}
}
package com.tansor.service.impl;
import com.tansor.dao.UserDao;
import com.tansor.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class UserServiceImpl implements UserService {
@Autowired //自动装配
@Qualifier("userDao") //加载指定name的bean
private UserDao userDao;//无需setter方法,暴力反射注入
}
简单类型的注入
package com.tansor.service.impl;
import com.tansor.dao.UserDao;
import com.tansor.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class UserServiceImpl implements UserService {
@Value("testValue")//简单类型注入
private String test;
}
简单类型注入(加载properties文件)
使用配置类载入properties文件
package com.tansor.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan("com.tansor")
@PropertySource({"jdbc.properties"}) //载入properties文件
public class SpringConfig {
}
在业务类中使用${jdbc.url}
引用properties文件中的参数
package com.tansor.service.impl;
import com.tansor.dao.UserDao;
import com.tansor.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class UserServiceImpl implements UserService {
@Value("${jdbc.url}")
public String url;
}
注解开发管理第三方Bean
导入DruidDataSource数据源
集中在SpringConfig管理
package com.tansor.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class SpringConfig {
//1.定义一个方法获得要管理的对象
//2.添加@Bean,表示当前返回值是个Bean
@Bean
public DataSource dataSource(){
DruidDataSource ds=new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
/*
测试类
*/
import com.tansor.config.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.sql.DataSource;
public class AppForAnnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource=ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}
分散到各个Config类
定义JdbcConfig.java专门用于JDBC配置操作
package com.tansor.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds=new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
在SpringConfig.java导入JDBC配置文件
package com.tansor.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({JdbcConfig.class}) //可以写多个
public class SpringConfig {
}
为第三方Bean注入依赖
第三方Bean简单类型注入
package com.tansor.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/spring")
private String url;
@Value("root")
private String userName;
@Value("root")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds=new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}
引入properties也可以,参考之前的jdbc.url那种参数引入(${jdbc.url})
第三方Bean引用类型注入
先在总Config类扫自动装配
package com.tansor.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(JdbcConfig.class)
@ComponentScan("com.tansor")
public class SpringConfig {
}
package com.tansor.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.tansor.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/spring")
private String url;
@Value("root")
private String userName;
@Value("root")
private String password;
@Bean
public DataSource dataSource(UserDao userDao){//此处按类型自动装配
System.out.println(userDao);
DruidDataSource ds=new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}