目录 | G:\8-CodeCloud\spring |
---|---|
项目名称 | spring_ioc |
项目文件夹 | com.imooc.ioc.demo2;com.imooc.ioc.demo3;com.imooc.ioc.demo4 |
项目名称 | spring_ioc_annotation |
项目文件夹 | com.imooc.ioc.demo1;com.imooc.ioc.demo2;com.imooc.ioc.demo3; |
1. SpringBean管理的方式:XML方式
1.1 Bean配置方式
- 采用无参数的构造方法的方式
- 采用静态工厂实例化的方式
- 实例工厂实例化的方式
applicationContext.xml配置如下:
但实际工作中基本都是无参数的构造方法方式,其余2种方式意义不大。
1.2 Bean配置详解
(1)id与name
区别在于name中可以有特殊字符。
(2)bean的作用域
实验如下:通过打印对象地址来区分是否是同一对象
@Test
public void demo1(){
//创建工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类的实例
Person person1 = (Person) applicationContext.getBean("person");
Person person2 = (Person) applicationContext.getBean("person");
System.out.println(person1);
System.out.println(person2);
}
(3)bean的生命周期
具体配置如下:
注意:
执行顺序 构造函数—>init-method—>destroy-method
destroy-method仅单例生效,并且只有在applicationContext工厂关闭的时候才会调用,工作中意义不大
完整的生命周期:
applicationContext2.xml中配置MyBeanPostProcessor
Man定义Spring Bean生命周期的步骤
package com.imooc.ioc.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class Man implements BeanNameAware,ApplicationContextAware,InitializingBean,DisposableBean{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("第二步:设置属性");
this.name = name;
}
public Man(){
System.out.println("第一步:Man被实例化了");
}
public void setup(){
System.out.println("第七步:Man被初始化了");
}
public void teardown(){
System.out.println("第十一步:执行自己的销毁方法,Man被销毁了");
}
@Override
public void setBeanName(String name) {
System.out.println("第三步:设置Bean的名称"+name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("第四步:了解工厂的信息");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("第六步:属性设置后");
}
public void run(){
System.out.println("第九步:执行业务方法");
}
@Override
public void destroy() throws Exception {
System.out.println("第十步:执行Spring 销毁方法");
}
}
MyBeanPostProcessor是Spring中重要的方法涉及后续的AOP,代码如下:
package com.imooc.ioc.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步:初始化前方法......");
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("第八步:初始化后方法......");
return bean;
}
}
具体的生命周期如下:
- Spring调用类的构造函数实例化
- DI:通过类的set方法初始化属性
- setBeanName 设置bean的名称
- setApplicationContext 了解工厂的信息
- 调用 MyBeanPostProcessor.postProcessBeforeInitialization 初始化前方法
- afterPropertiesSet 属性设置后
- init-method(配置文件中配置),进行初始化
- 调用 MyBeanPostProcessor.postProcessAfterInitialization 初始化后方法
- 执行业务方法
- destroy执行Spring 销毁方法
- destroy-method(配置文件中配置)执行自己的销毁方法,对象被销毁了
(4)Bean的增强
新建UserDao.java
package com.imooc.ioc.demo3;
public class UserDaoImpl implements UserDao {
@Override
public void findAll() {
System.out.println("查询用户。。。。");
}
@Override
public void save() {
System.out.println("保存用户。。。。");
}
@Override
public void update() {
System.out.println("修改用户。。。。");
}
@Override
public void delete() {
System.out.println("删除用户。。。。");
}
}
改造MyBeanPostProcessor.java,对userDao的sava方法进行增强
package com.imooc.ioc.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步:初始化前方法......");
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("第八步:初始化后方法......");
if ("userDao".equals(beanName)) {
Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("save".equals(method.getName())){
System.out.println("权限校验");
return method.invoke(bean,args);
}
return method.invoke(bean,args);
}
});
return proxy;
}else {
return bean;
}
}
}
(5)Bean的属性注入
构造函数属性注入:
set方法属性注入1
set方法属性注入2
此外还有p名称空间属性注入、SpEL属性注入、复杂类型属性注入,由于工作中不常用就不记录了
2. SpringBean管理的方式:注解方式
2.1 Bean的管理
(1)开启注解扫描:如果下面的包中有注解就交给spring进行管理
(2)用注解代替XML文件定义Bean
(3)用注解进行属性注入
属性注入的根本目的是为了初始化属性,使用属性的方法完成相应的功能
@Autowired 按照类型注入,如果存在两个相同Bean类型相同,则按照名称注入
@Autowired + @Qualifier("userDao") 按照类型注入的同时指定名称
@Resource(name="userDao") //@Resource 相当于@Autowired + @Qualifier
代码UserService.java
package com.imooc.demo1;
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 org.springframework.stereotype.Service;
import javax.annotation.Resource;
/*
* Spring的Bean管理的注解方式
* 传统方式需要在applicationContext.xml中配置
*
*/
//@Component("userService")
@Service("userService") //这里的名称,实际等效于bean id
public class UserService {
@Value("米饭")
private String something;
@Autowired //按照类型注入,如果存在两个相同Bean类型相同,则按照名称注入
@Qualifier("userDao") //单单用Qualifier注解没有注入userDao
@Resource(name="userDao") //@Resource 相当于@Autowired + @Qualifier
private UserDao userDao;
public String sayHello(String name){
return "Hello"+name;
}
public void eat(){
System.out.println("eat:" + something);
}
public void save(){
System.out.println("service 保存用户方法。。。");
userDao.save();
}
}
(4)其他注解
@PostConstruct 相当于XML中的init-method
@PreDestroy相当于XML中的destroy-method,仅单例支持
@Scope("prototype")相当于XML中的scope
XML文件中的配置方式:
@PostConstruct @PreDestroy的使用方式:
package com.imooc.demo2;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component("bean1")
public class Bean1 {
@PostConstruct
public void init(){
System.out.println("bean1 init 初始化方法。。。");
}
public void say(){
System.out.println("bean1 say方法执行。。。");
}
@PreDestroy
public void destroy(){
System.out.println("bean1 destroy销毁方法。。。");
}
}
@Scope("prototype")的使用方式,此时没有@PreDestroy
package com.imooc.demo2;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component("bean2")
@Scope("prototype")
public class Bean2 {
@PostConstruct
public void init(){
System.out.println("bean2 init 初始化方法。。。");
}
public void say(){
System.out.println("bean2 say方法执行。。。");
}
@PreDestroy
public void destroy(){
System.out.println("bean2 destroy销毁方法。。。");
}
}