IOC
IoC(inversion of Controller) 控制反转
主动式: 通过创建对象,创建对象使用的时候使用new的方式进行
被动式: 资源的获取不是通过人进行设置,而是交给一个容器设置
第一个Spring程序
需要导入spring的5个核心jar包和一个日志commons-login
编写实体类
//创建实体类public class User {private String name;private Integer age;private String sex;}
编写配置文件
<!-- 创建配置文件名称为applicationContext.xml --><bean id="user" class="com.xztx.entity.User"><property name="name" value="smith"></property><property name="age" value="20"></property><property name="sex" value="女"></property></bean>
测试
public class Test{private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");public static void main(String[] args){test01();}public static void test01(){User user = context.getBean("user",User.class);//这里使用了反射可以不让对象进行强制转换System.out.println(user);}}
DI
DI(dependency injection) 依赖注入
DI是IoC的一个实现方式
注入的方式通常有两种: set方式注入和将要学习的通过配置文件方式进行注入
//把配置文件放在src下边ApplicationContext context = new ClassPathXmlApplicationContext("类路径下");//如果不想把配置文件放在src下边ApplicationContext context = new FileSystemApplicationContext("系统目录下");
获取配置文件的几种方式
context.getBean("传入唯一值");//通过id值context.getBean("传入实体类的类名.class")//通过类型获取context.getBean("要查找的唯一值",查找的类型.class);//通过类型查找context.getBean();//通过构造器
配置文件可以创建多个对象,创建的所有对象在获取容器的时候都会被实例化
<bean id="user1" class="com.xztx.entity.User"><property name="name" value="jack"></property>...<!-- 这是第一个赋值的对象 --></bean><bean id="user1" class="com.xztx.entity.User"><property name="name" value="jack"></property>...<!-- 这是第二个赋值的对象 --></bean>
public class Test{private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");public static void main(String[] args){test01();}public static void test01(){//这里只是获取到user1中的值,但是程序在运行的时候虽然没有显示user2的值,但是这个对象依然被创建了User user = context.getBean("user1",User.class);System.out.println(user);}}
配置文件给属性赋值的方式
<!-- 通过property给属性赋值 --><!-- 赋值的时候如果属性是基本数据类型使用value赋值,如果是对象类型使用ref进行赋值 --><bean parent="这个的id" abstract="true"><!-- 使用parent继承这个类的配置信息,abstract不能被实例,只能被继承 --><property name="" value=""></property><property name=""><!-- 使用内部bean --><bean class=""><property name="" value=""></property></bean></property><!-- 通过构造器给属性赋值 --><constructor-arg name="" value="jack"></constructor-arg><!-- 通过构造器索引惊醒赋值,索引从0开始 --><constructor-arg value="" index="0"></constructor-arg><!-- 通过类型进行赋值 --><constructor-arg value="" type="String"></constructor-arg></bean>
工厂模式给对象赋值
静态工厂
<!-- 静态工厂模式 --><!-- factory-method:指定静态工厂实现的方法名称 --><bean id="" class="使用工厂的全类名" factory-method="" ><!-- 如果工厂类的方法里边有参数需要设置参数 --><constructor-arg value=""></constructor-arg></bean>
就是工厂本身创建对象,工厂类名.工厂方法名
实体类
public class Dog {private String name;private Integer id;private Integer age;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}}
创建静态工厂 staticFactory
public class StaticFactory {public User getDog(String name){Dog dog = new Dog();dog.setId(1);dog.setAge(3);return dog;}}
编写配置文件
<bean id="dog" class="com.wyxz.factory.StaticFactory" factory-method="getUser"><constructor-arg value="大黄"></constructor-arg></bean>
测试文件省略
实例工厂
工厂本身需要创建对象 工厂 = new 工厂().工厂方法名()
实例工厂 InstanceFactory = new InstanceFactory ().getUser();
<!-- 实例工厂模式 --><!--class 指定的是实体类的全类名factory-method 指定使用哪个工厂方法factory-bean 指定使用哪个工厂实例--><bean id="" class="使用本类的全类名" factory-method="" factory-bean=""></bean>
实体类不变
编写工厂类
public class InstanceFactory {public User getDog(String name){Dog dog = new Dog();dog.setId(1);dog.setAge(3);return dog;}}
3. 配置文件
<bean id="isntanceFactory" class="com.wyxz.entity.Dog" factory-method="getDog" factory-bean="InstanceFactory"></bean>
测试省略
factory-bean
factory-bean 是spring的一个接口,如果要是实现了这个接口,spring都会认为是一个工厂类
//可以实现一个Factory 创建一个工厂对象public class MyFactory implements FactoryBean<Dog> {/**1. getObject()方法,返回对象的创建User user = new User();*/@Overridepublic Dog getObject() throws Exception {return null;}/**2. getObjectType()方法,返回创建的对象的类型*/@Overridepublic Class<?> getObjectType() {return null;}/**3. isSingleton()方法,是否是单例return true/false;*/@Overridepublic boolean isSingleton() {return false;}}
工厂创建好之后怎样让spring识别这个类呢,需要在配置文件中如下配置:
<bean id="myFactory" class="com.xztx.factory.MyFactory" ></bean>
bean的生命周期
创建实体类
public class Dog {private String name;private Integer id;private Integer age;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}}
再配置文件中设置生命周期
<!-- 注意 注意 生命周期方法可以抛异常,但是方法一定不能有参数 --><bean id="dog" class="com.wyxz.entity.Dog" init-method="init" destory-method="destory"></bean>
bean的后置处理器
bean的后置处理器是spring的一个接口,可以在bean的初始化前后调用方法,需要实现BeanPostProcessor接口
public class MyAfter implements BeanPostProcessor {//实现相关方法/**postProcessBeforeInitialization() 初始化方法之前调用*/@Overridepublic Object postProcessBeforeInitialization(Object o, String s) throws BeansException {System.out.println( s + "方法被调用,名字是" + o);return o;}/**postProcessorAfterInitialization() 初始化方法之后调用*/@Overridepublic Object postProcessAfterInitialization(Object o, String s) throws BeansException {System.out.println( s + "方法被调用,名字是" + o);return null;}}
在配置文件中注册
<bean id="myAfter" class="com.xztx.controller.MyAfter" ></bean>
spring连接池
编写连接数据库的基本配置(外部配置)
user=rootpassword=123456jdbcUrl=jdbc:mysql://localhost:3306/testdriverClass=com.mysql.jdbc.Driver
使用xml文件读取配置文件信息
<!-- 对配置文件进行扫描,读取配置文件 --><context:property-placeholder location="classpath:配置文件名.properties"/><bean id="dataSource" class="要连接的连接池的全类名"><!-- 获取配置文件中的信息 --><property name="name" value="${name}"></property><property name="password" value="${password}"></property><property name="jdbcrUrl" value="${driverUrl}"></property><property name="driverClass" value="${driverClass}"></property></bean>
public class TestConnection {public static void main(String[] args){ApplicationContext context = new ClassPathXmlApplicationContext("jdbc.xml");Connection connect = context.getBean("dataSource");System.out.println(connect);}}
自动装配
在bean中添加属性 autowired进行自动装配
<!-- 使用autowired为属性自动赋值 --><bean id="dog" class="com.wyxz.entity.Dog" autowired="default"></bean>
public class Dog {private String name;private Integer id;private Integer age;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}}
spring注解声明及配置
@Service : 给service添加的注解
@Controller: 给servlet的组件添加的注解
@reponsity: 给数据层(dao层)的组件添加的注解
@Component:给不是以上几层的组件添加的注解
@Controllerpublic class UserServlet{}@Reponsitypublic class UserDao{}@Servicepublic class UserService{}
那么在类上声明完之后如何让spring识别呢?
在配置文件中加入如下配置
<!-- 通过spring的扫描器扫描加了注解的类,要扫描的基础包的类名,比如这个就是扫描com.xztx下边的所有子包和文件 --><context:component-scan base-package="com.wyxz" >
Autowired注解实现自动装配
使用@Autowired进行装配,如果找到了就自动装配,如果没有找到就报错,可以使用@Qualifier指定一个新的id值,如果找到了继续装配,如果没有找到报错,可以给autowired添加一个属性require属性设置true或者false
和@Autowired注解相同的注解还有@Resource注解
都是自动装配,但是@Resource没有@Autowired强大,因为Autowired是spring提供的,而Resource是java提供的,Resource扩展性更强大
<!-- 要扫描的基础包的类名,比如这个就是扫描com.xztx下边的所有子包和文件,需要在配置文件加入此配置 --><context:component-scan base-package="com.wyxz" >
public class UserDao{}public class UserServiceprivate UserDao userDao;public void save(){System.out.println("调用suerDao保存数据");}}public class UserServlet {@AutoWired() //自动的为userService赋值,不使用new的方式private UserService userService;public void do(){System.out.println("将信息传递给userService保存");userService.save();}}
public class Test{private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");public static void main(String[] args){test01();}public static void test01(){//这里只是获取到user1中的值,但是程序在运行的时候虽然没有显示user2的值,但是这个对象依然被创建了UserServlet userServlet = context.getBean("userServlet",UserServlet.class);userServlet.do();//调用userServlet的do方法}}
Spring单元测试
spring-test的单元测试包
@ContextConfiguration(location="xml文件") 指定spring的配置文件位置
@RunWith() 可以指定需要使用驱动进行单元测试,默认使用的是JUnit进行测试
导入spring-test的包
@ContextConfiguration(location="applicationContext.xml")@RunWith(SpringJUnit4ClassRunner.class)//指定单元测试框架使用类型,需要使用反射获取测试类的类型public class Test {//private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");@AutowiredUserServlet userServlet;public static void main(String[] args){}}
面试题
BeanFactory和ApplicationContext的区别?
ApplicationContext是BeanFactory的子接口
BeanFactory bean是工厂接口,负责创建bean实例
ApplicationContext是容器接口,更多的负责容器红能的实现,容器可以从map中获取bean,并且aop,di在applicationContext接口的这些类里面
beanFactory最底层的接口,applicationContext是使用的接口




