4、XML实现DI
DI给对象属性赋值
首先我们创建一个User类,并通过lombok添加构造方法和set、get方法
@Data
public class User {
private int uid;
private String username;
private String password;
}
1.通过set方法
<bean id="u1" class="com.mdh.demo.User">
<property name="uid" value="1"></property>
<property name="username" value="张三"></property>
<property name="password" value="123456"></property>
</bean>
先通过无参构造实例化,再用set方法赋值
2.通过有参构造
<bean id="u2" class="com.mdh.demo.User">
<!-- 此处的参数:index表示形参下标,name表示形参名字,value表示基本类型的值,ref表示自定义的引用类型的值-->
<constructor-arg index="0" value="2"></constructor-arg>
<constructor-arg index="1" value="李四"></constructor-arg>
<constructor-arg index="2" value="123456"></constructor-arg>
</bean>
通过有参构造实例化
3.通过p名称空间和c名称空间
<beans xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c">
<bean id="u3" class="com.mdh.demo.User" p:uid="3" p:username="王五" p:password="123456"></bean>
<bean id="u4" class="com.mdh.demo.User" c:uid="4" c:username="王六" c:password="123456"></bean>
</beans>
实际上是前两种的简化写法,注意要在beans里加约束
4.注入空值和特殊符号
<bean id="u1" class="com.mdh.demo.User">
<!-- 空值 -->
<property name="uid">
<null></null>
</property>
<!-- 特殊符号使用转义字符 <为< >为> &为&-->
<property name="username" value="&"></property>
<!-- CDATA原样设置 -->
<property name="password">
<value>
<![CDATA[内容]]>
</value>
</property>
</bean>
5.bean引用另一个bean
创建一个Student类,其属性中有Score类,并通过lombok添加构造方法和set、get方法
@Data
public class Score{
private int java;
private int cpp;
}
@Data
public class Student {
private String name;
private Score score;
}
(1)引用外部bean
<bean id="u1" class="com.mdh.demo.User">
<!-- 空值 -->
<property name="uid">
<null></null>
</property>
<!-- 特殊符号使用转义字符 <为< >为> &为&-->
<property name="username" value="&"></property>
<!-- CDATA原样设置 -->
<property name="password">
<value>
<![CDATA[内容]]>
</value>
</property>
</bean>
(2)引用内部bean
<bean id="stu2" class="com.mdh.demo.Student">
<property name="name" value="李四"></property>
<property name="score">
<bean class="com.mdh.demo.Score">
<property name="java" value="100"></property>
<property name="cpp" value="100"></property>
</bean>
</property>
</bean>
(3)级联引入bean
<bean id="score3" class="com.mdh.demo.Score"></bean>
<bean id="stu3" class="com.mdh.demo.Student">
<property name="name" value="王五"></property>
<property name="score" ref="score3"></property>
<property name="score.java" value="100"></property>
<property name="score.cpp" value="100"></property>
</bean>
原理为用反射调用get方法,获取对象之后,再赋值
6.注入集合
例如有这样一个类
@Data
public class Students {
private String[] books;
private List<String> bookList;
private Set<String> bookSet;
private Map<String,String> bookMap;
private List<Book> bookList2;
}
public class Book {
private String name;
private String author;
}
配置xml
<bean id="students1" class="com.mdh.demo.Students">
<!-- array数组注入 -->
<property name="books">
<array>
<value>java</value>
<value>cpp</value>
</array>
</property>
<!-- list集合注入 -->
<property name="bookList">
<list>
<value>java</value>
<value>cpp</value>
</list>
</property>
<!-- set集合注入 -->
<property name="bookSet">
<set>
<value>java</value>
<value>cpp</value>
</set>
</property>
<!-- map集合注入 -->
<property name="bookMap">
<map>
<entry key="java" value="bite"></entry>
<entry key="cpp" value="bite"></entry>
</map>
</property>
<!-- list对象集合注入 -->
<property name="bookList2">
<list>
<ref bean="b1"></ref>
<ref bean="b2"></ref>
</list>
</property>
</bean>
<!-- 声明多个book对象 -->
<bean id="b1" class="com.mdh.demo.Book" p:name="java" p:author="bite" ></bean>
<bean id="b2" class="com.mdh.demo.Book" p:name="cpp" p:author="bite" ></bean>
7.工厂方式获取bean
<bean id="bookFactory" class="com.mdh.factory.BookFactory"></bean>
实现FactoryBean接口
public class BookFactory implements FactoryBean<Book> {
@Override
public Book getObject() throws Exception {
return new Book();
}
@Override
public Class<?> getObjectType() {
return null;
}
}
在getBean时,需要用Book对象接收
什么是工厂模式
某个特定的类型对象由工厂统一生产,以达到对对象的统一管理
一些Bean标签
- lazy-init:true懒加载(延迟加载)false立即加载
- init-method:设置对象初始化阶段调用的方法
- destory-method:设置对象销毁阶段调用的方法
- scope:设置作用域
5、bean作用域、生命周期与自动装配
bean作用域
前两个是SpringCore项目都可以用,后三个是基于Web的项目可用
1.singleton
描述:该作⽤域下的Bean在IoC容器中只存在⼀个实例
2.prototype
描述:每次对该作⽤域下的Bean的请求都会创建新的实例
3.request
描述:每次http请求会创建新的Bean实例,类似于prototype
场景:⼀次http的请求和响应的共享Bean
4.session
描述:在⼀个http session中,定义⼀个Bean实例
场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息
5.application
描述:在⼀个http servlet Context中,定义⼀个Bean实例
场景:Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息
bean的生命周期
所谓的⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程
1.读取beanDefinition信息 实例化Bean(执行构造器)
2.并设置Bean的属性为bean赋值(执行set方法)
3.根据其实现的Aware接口(主要是 BeanFactoryAware接口,BeanFactoryAware,ApplicationContextAware)设置依赖信息(执行set方法)
4.把bean实例传递给bean的前置处理器方法完成initial前的自定义逻辑
5.调用Bean自身定义的init方法,初始化bean(调用bean的初始化方法)
6.把bean实例传递给bean的后置处理器方法主要是代理类增强
7.bean的获取使用(getBean方法)
8.容器关闭并销毁bean(调用销毁方法)
通知处理器的使用
<!-- 配置后置通知处理器 -->
<bean id="myBeanProcessor" class="com.mdh.demo.MyBeanProcessor"></bean>
对于所有bean都会影响
public class MyBeanProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//Object bean 要干预的bean
//String beanName bean的id
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return null;
}
}
bean的自动装配
自动注入bean,例如
public class Score{
private int java;
private int cpp;
}
public class Student {
private String name;
private Score score;
}
autowire属性控制自动将容器中的对象注入到当前对象的属性上
byName根据目标id值和属性值注入,要保证当前对象的属性值和目标对象的id值一致
byType根据类型注入,要保证相同类型的目标对象在容器中只有一个实例
<bean id="score" class="com.mdh.demo.Score"></bean>
<bean id="student" class="com.mdh.demo.Student" autowire="byName"></bean>
6、引入外部属性配置文件
在resources目录下用.properties结尾的文件来配置
username="root"
pa55word="123456"
在xml里就可以引入
<!-- 读取jdbc.properties配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
7、注解方式管理bean
注解方式实现IOC
@Component【组件类】 该注解有四个子注解 (1)@Controller【控制器】 (2)@Service【业务逻辑类】 (3)@Repository【数据持久类】 (4)@Configuration【配置类】
第一步:在xml文件里开启注解扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 设置为true,则使用默认扫描过滤器,可以识别并包含所有五个注解 -->
<!-- 设置为false,则自己设置扫描哪些注解 -->
<context:component-scan base-package="com.mdh.demo" use-default-filters="false">
<!-- include 控制只扫描哪些注解-->
<!-- exclude 控制不扫描哪些注解-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
第二步:在类上添加注解,让spring容器给我们创建bean实例并存储于容器中
@Component("user1")
//可以命名id,
//如果不命名,默认是类首字母小写
public class User {
private int uid;
private String username;
private String password;
}
注解方式实现DI
1.对象注入
例如在service层调用dao层 使用Autowired注解注入,如果有多个实现类,则可以配合Qualifier注解使用 也可以使用Resource实现
@Service
public class UserServiceImpl implements UserService{
@Autowired
@Qualifier("userDaoImplB")
//@Resource(name="userDaoImplB")
private UserDao userDao;
@Override
public void add(){
userDao.add();
}
}
2.注入基础数据类型(8+String)
@Value("zhangsan")
private String name;
@Value("1")
private Integer age;
也可以通过外部属性配置文件注入 首先配置properties文件
name="张三"
age=1
其次配置xml
<context:property-placeholder location="classpath:*.properties"></context:property-placeholder>
然后就可以使用了(可能出现中文乱码问题)
@Value("${name}")
private String name;
@Value("${age}")
private Integer age;
配置类方式实现IOC和DI
可以通过ComponentScan配置扫描路径 也可以通过PropertySource注入外部属性配置文件
@ComponentScan(basePackages = "com.mdh")
@PropertySource("classpath:aaa.properties")
public class SpringConfig{
}
在使用时,就从此类的字节码文件中获取spring上下文对象
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("SpringConfig.class");
User user = context.getBean("user1",User.class);
System.out.println(user);
}
}
评论( 0 )