Java网课基础笔记(11)19-07-24

用eclipse安装Spring插件用了好久才搞懂,但是安装的时候又出现问题。所以昨天一天都没更新博客,落下一天的博客记录有点不爽。spring框架估计要搞好久才能上手。还有hibernate没有动手过,所以学完Spring后打算找关于hibernate的项目熟悉一下

天,搞安装弄了一天半,测试成功第一个例子也用了半天,语法逻辑错误不可怕,可怕的是每次学习新的东西出现的那各种五花八门的配置错误。害怕

 

1.传统方式调用函数

//Dao接口
public interface IUserDao {
	//根据用户名和密码查询数据
	public void findByUsernameAndPassword();
}
//Service接口
public interface IUserService {
	//登录
	public void login();
}
//Dao具体实现类
public class UserDaoImpl implements IUserDao{

	@Override
	public void findByUsernameAndPassword() {
		// TODO Auto-generated method stub
		System.out.println("UserDaoImpl--Dao层被调用了");
	}
}
//Service具体实现类
public class UserServiceImpl implements IUserService{
	@Override
	public void login() {
		// TODO Auto-generated method stub
		System.out.println("UserServiceImpl--service层被调用了");
		//传统方式调用dao
		IUserDao userDao=new UserDaoImpl();
		userDao.findByUsernameAndPassword();
	}
}
//测试入口类
public class SpringText {
	//注解,只允许这一方法(单元测试)
	@Test
	public void test01d() {
		IUserService userService=new UserServiceImpl();
		userService.login();
	}
}

2.用spring的Ioc和依赖注入

//UserDao接口
package com.igeek;
public interface IUserDao {
	//根据用户名和密码查询数据
	public void findByUsernameAndPassword();
}

//UserService接口
package com.igeek;
public interface IUserService {
	//登录
	public void login();
}
//UserDao实现类
package com.igeek;
public class UserDaoImpl implements IUserDao{
	@Override
	public void findByUsernameAndPassword() {
		// TODO Auto-generated method stub
		System.out.println("UserDaoImpl--Dao层被调用了");
	}
}
//UserService实现类
package com.igeek;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceImpl implements IUserService{
	//定义的成员变量必须和配置文件中的name对应
	private IUserDao userDao;
	//spring框架创建UserServiceImpl对象后,通过setUserDao方法给userDao赋值
	public void setUserDao(IUserDao userDao) {
		this.userDao = userDao;
	}
	@Override
	public void login() {
		// TODO Auto-generated method stub
		System.out.println("UserServiceImpl--service层被调用了");
		//传统方式调用dao
		//IUserDao userDao=new UserDaoImpl();
		
		//spring的配置方式new对象,IoC控制反转
		//读取applicationContex.xml文件,获取bean节点
		//ApplicationContext是一个接口,ClassPathXmlApplicationContext是它的一个实现类	
//		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//		//获取bean
//		IUserDao userDao=(IUserDao) ac.getBean("userDao");
		userDao.findByUsernameAndPassword();
	}
}
//测试入口类
package com.igeek;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringText {
	//注解,只允许这一方法(单元测试)
	@Test
	public void test01d() {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		IUserService userService=(IUserService) ac.getBean("userService");
		//IUserService userService=new UserServiceImpl();
		userService.login();
	}
}

applicationContext.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对应一个对象 -->
	<!-- bean是spring工厂帮你new的一个对象(反射机制) -->
	<!-- class是要new的对象的类型的字符串表现形式(一定要全类名) -->
	<!-- id/name:标识对象的名字,用来获取bean对象的标识,习惯上,这个名字命名为接口的名字,首字母小写 -->
	<bean id="userDao" class="com.igeek.UserDaoImpl"></bean>
	<!-- 
	DI(依赖注入) serivice要依赖userDao
	双方都必须是bean,在创建service都时候,主动将dao的依赖对象交给service
	 -->
	 <bean id="userService" class="com.igeek.UserServiceImpl">
	 <!-- 
	 setter方法注入
	 name:要与类中的成员变量userDao一致,调用userDao的setUserDao方法
	 ref:Spring容器中定义的bean对象的名字
	  -->
		<property name="userDao" ref="userDao"></property>
		</bean>
</beans>

log4j.properties配置文件

#OFF,systemOut,logFile,logDailyFile,logRollingFile,logMail,logDB,ALL 
log4j.rootLogger =ALL,systemOut

#\u8F93\u51FA\u5230\u63A7\u5236\u53F0 
log4j.appender.systemOut = org.apache.log4j.ConsoleAppender 
log4j.appender.systemOut.layout = org.apache.log4j.PatternLayout 
log4j.appender.systemOut.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n 
log4j.appender.systemOut.Threshold = DEBUG 
log4j.appender.systemOut.ImmediateFlush = TRUE 
log4j.appender.systemOut.Target = System.err

#\u8F93\u51FA\u5230\u6587\u4EF6 
log4j.appender.logFile = org.apache.log4j.FileAppender 
log4j.appender.logFile.layout = org.apache.log4j.PatternLayout 
log4j.appender.logFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n 
log4j.appender.logFile.Threshold = DEBUG 
log4j.appender.logFile.ImmediateFlush = TRUE 
log4j.appender.logFile.Append = TRUE 
log4j.appender.logFile.File = ../Struts2/WebRoot/log/File/log4j_Struts.log 
log4j.appender.logFile.Encoding = UTF-8 

3.ApplicationContext直译为应用上下文,是用来加载Spring框架配置文件,来构建Spring的工厂对象,它也称之为Spring容器的上下文对象,也称之为Spring的容器。

ApplicationContext只是BeanFactory(Bean工厂,Bean就是一个Java对象)一个子接口

4.为什么不直接使用顶层接口对象来操作呢?

  • BeanFactory采取延迟加载,第一次getBean时才会初始化Bean
  • BeanFactory的用法:

                  Beanfactory ac=new XmlBeanFactory(new ClassPathResouse("applicationContext.xml"));

                  BeanFactory ac =new XmlBeanFactory(new FileSystemResourse("D:\\applicationContext.xl"));

  • ApplicationContex是对BeanFactory扩展,提供了更多功能

         国际化处理

        事件传递

        Bean自动装配

        各种不同应用层的Contex实现

ApplicationContext更加强大,所以现在开发人员基本没人使用BeanFactory

5.实例化bean的四种方法

//Bean1
package com.igeek;
public class Bean1 {
	private String name;
	//第一种:通过空的构造方法创建
	public Bean1() {
		// TODO Auto-generated constructor stub
	}
	public Bean1(String name) {
		this.name = name;
	}
}
//Bean2
package com.igeek;
public class Bean2 {
	//第二种:静态的构造方法
	public static Bean2 getBean2() {
		return new Bean2();
	}
}
//Bean3
package com.igeek;
public class Bean3 {
}
//Bean3Factory
package com.igeek;
public class Bean3Factory {
	public Bean3 getBean3() {
		return new Bean3();
	}
}
//Bean4
package com.igeek;
public class Bean4 {
}
//FactoryBean
package com.igeek;
import org.springframework.beans.factory.FactoryBean;
public class Bean4FactoryBean implements FactoryBean<Bean4>{
	@Override
	public Bean4 getObject() throws Exception {
		// TODO Auto-generated method stub
		//可以写一些初始化数据、连接等代码
		return new Bean4();
	}
	@Override
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return null;
	}
}
//测试类
package com.igeek;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
	@Test
	public void test1() {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		Bean1 bean1=(Bean1) ac.getBean("bean1");
		System.out.println(bean1);
	}
	@Test
	public void test2() {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		Bean2 bean2=(Bean2) ac.getBean("bean2");
		System.out.println(bean2);
	}
	@Test
	public void test3() {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		Bean3 bean3=(Bean3) ac.getBean("bean3");
		System.out.println(bean3);
	}
	@Test
	public void test4() {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		Bean4 bean4=(Bean4) ac.getBean("bean4");
		System.out.println(bean4);
	}
	
}
//applicationContext.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"
	xmlns:c="http://www.springframework.org/schema/c"
	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">
	<!-- 第一种:用空的构造方法 最常用-->
	<bean id="bean1" class="com.igeek.Bean1"></bean>
	<!-- 
	第二种:静态工厂创建bean  框架初始化用得比较多
	用来自定义工厂,让spring的工厂来调用自定义的工厂,可以将对象的创建权限交给自定义的工厂
	 -->
	<bean id="bean2" class="com.igeek.Bean2" factory-method="getBean2"></bean>
	<!-- 第三种:实例工厂的方式实例化bean,bean3Factory是实例化工厂  框架初始化用得比较多   -->
	<bean id="bean3Factory" class="com.igeek.Bean3Factory"></bean>
	<!-- factory-bean 相当于ref,引用一个bean对象 -->
	<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
	<!-- 
	第四种:实现接口FactoryBean(spring框架底层用得比较多
	Spring在准备实例化bean的时候,new Bean4FactoryBean,没有急着返回bean对象
	会判断,类型对象是否实现了FactoryBean接口,如果实现了,就调用接口的getObject()方法
	得到bean实例,返回bean对象
	 -->
	<bean id="bean4" class="com.igeek.Bean4FactoryBean" ></bean>
	<!-- beanFactory和FactoryBean的区别:
	beanFactory是找配置文件的顶层接口
	FactoryBean是bean的生成工具,获取bean
	 -->
</beans>

6.bean的作用域

Spring 框架支持以下五个作用域,分别为singleton、prototype、request、session和global session,5种作用域说明如下所示,

注意,如果你使用 web-aware ApplicationContext 时,其中三个是可用的。    

作用域描述
singleton

在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值

prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean() 
request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境

singleton 作用域:

singleton 是默认的作用域,也就是说,当定义 Bean 时,如果没有指定作用域配置项,则 Bean 的作用域被默认为 singleton。 

当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

也就是说,当将一个bean定义设置为singleton作用域的时候,Spring IoC容器只会创建该bean定义的唯一实例。

Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域

prototype 作用域

当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

//SingletonBean
package com.igeek.scope;
public class SingletonBean {
	public SingletonBean() {
		// TODO Auto-generated constructor stub
		System.out.println("SingletonBean:初始化");
	}
}

//PrototypeBean
package com.igeek.scope;
public class PrototypeBean {
	public PrototypeBean() {
		// TODO Auto-generated constructor stub
		System.out.println("PrototypeBean:初始化");
	}
}
//测试类
package com.igeek;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.igeek.scope.PrototypeBean;
import com.igeek.scope.SingletonBean;
public class SpringTest1 {
	@Test
	public void testScope() {
	//1,先构建实例化获取spring容器
	ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
	//2,看看多次获取bean的时候是不是同一个
	//单例模式:节省内存开销(只初始化一次)
	SingletonBean singletonBean1=(SingletonBean) ac.getBean("singletonBean");
	SingletonBean singletonBean2=(SingletonBean) ac.getBean("singletonBean");
	System.out.println(singletonBean1);
	System.out.println(singletonBean2);
	
	//多例模式:(初始化两次)
	PrototypeBean prototypeBean1=(PrototypeBean) ac.getBean("prototypeBean");
	PrototypeBean prototypeBean2=(PrototypeBean) ac.getBean("prototypeBean");
	System.out.println(prototypeBean1);
	System.out.println(prototypeBean2);
	}
}
//applicationContext.xml里增加
<!-- bean的作用域 -->
	 <!-- spring默认单例scope="singleton" ,可以不用配置-->
	 <bean id="singletonBean" class="com.igeek.scope.SingletonBean" scope="singleton"></bean>
	 <bean id="prototypeBean" class="com.igeek.scope.PrototypeBean" scope="prototype"></bean>

7.Bean的生命周期

Bean的定义——Bean的初始化——Bean的使用——Bean的销毁 

通过init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。

通过destroy-method 指定一个方法,销毁对象前调用该方法。

 

关于数据(一些属性等等)的初始化

  1. 直接赋值
  2. 在构造器中初始化
  3. 使用单独的初始化方法
//bean对象
package com.igeek.xmllifecycle;
public class LifeCycleBean {
	//三种初始化方式
	//1.初始化成员变量
	private String name="tom";//初始化成员变量
	public LifeCycleBean() {
		// TODO Auto-generated constructor stub
		System.out.println("LifeCycleBean 构造器被调用了");
		//2.通过构造方法初始化
		this.name="herl";
	}
	//构造方法调用后执行此方法,需要在xml中配置后才能生效
	public void init() {
		System.out.println("LifeCycleBean 构造器调用后执行");
		//3.单独的初始化方法来初始化数据
		this.name="feng";
	}
	//业务方法
	public void save() {
		System.out.println("执行了业务save方法");
	}
	//bean销毁前调用的方法
	public void destroy() {
		System.out.println("LifeCycleBean -destroy销毁前调用");
		System.out.println(name);
	}

}

//测试类
package com.igeek.xmllifecycle;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringText {
	@Test
	public void testCycle() {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		LifeCycleBean lifeCycleBean=(LifeCycleBean) ac.getBean("lifeCycleBean");
		lifeCycleBean.save();
		//为什么没有销毁方法调用?
		//原因:使用debug模式,jvm直接就关了,spring容器还没有来得及销毁对象,所以看不到
		//解决:可以手动销毁spring容器,只能销毁单例的对象
		((ClassPathXmlApplicationContext)ac).close();
	}
}

//applicationContext.xml中增加
<!-- bean的生命周期 -->
	 <bean id="lifeCycleBean" class="com.igeek.xmllifecycle.LifeCycleBean"
	 init-method="init" destroy-method="destroy" scope="singleton"
	 ></bean>

8.后处理bean

Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理。

BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。你也可以在 Spring 容器通过插入一个或多个 BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。

//在7.的基础上增加类
package com.igeek.xmllifecycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor{
	//初始化之后调用
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		if(beanName.equals("lifeCycleBean")) {
			System.out.println(beanName+"在初始化之后增强");
		}
		return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
	}
	//初始化之前调用 bean:返回的bean;beanName:bean的名称
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		if(beanName.equals("lifeCycleBean")) {
			System.out.println(beanName+"在初始化之前增强");
		}
		return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
	}
}
//applicationContext.xml中增加
<!-- 后处理bean -->
	 <bean class="com.igeek.xmllifecycle.MyBeanPostProcessor"></bean>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值