IOC:控制反转,其思想是反转资源获取的方向,传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器适时的返回资源。而应用了 IOC 之后,则是**容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源。**这种行为也被称为查找的被动形式。
DI:依赖注入,IOC的另一种表述方式,即**组件以一些预先定义好的方式(setter方法)**接受来自容器的资源注入。
可见,有了IOC容器之后,对象的创建都是在容器中进行,用户所要做的只是从容器中获取已经创建好的对象而已
2.1.1 在 xml 文件中通过全类名(反射)来配置 Bean
class: bean 的全类名, 通过反射的方式在 IOC 容器中创建 Bean, 所以要求 Bean 中必须有无参的构造器
id: 标识容器中的 bean. id 唯一.
2.1.2 在 xml 中通过静态工厂方法来配置 Bean
调用静态工厂方法创建 Bean 是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节
创建 Bean 实例
public class Car {private String brand;private String corp;private double price;public Car(String brand, String corp, double price) {this.brand = brand;this.corp = corp;this.price = price;}}
/*** 静态工厂方法: 只要调用某一个类的静态方法就可以返回 Bean 的实例*/
public class StaticCarFactory {private static Map cars = new HashMap<>();static {cars.put("audi", new Car("audi", "xixi", 2000));cars.put("ford", new Car("ford", "hello", 401111));}public static Car getCar(String name) {return cars.get(name);}}
配置 Bean:
class
属性:指向静态工厂方法的全类名
factory-method
:指向静态工厂方法的名字
constructor-arg
:如果工厂方法需要传入参数, 则用 constructor-arg 来配置参数
结果:
Car [brand=audi, corp=xixi, price=2000.0]
2.1.3 在 xml 中通过实例工厂方法配置 Bean
将对象的创建过程封装到另一个对象实例的方法中,当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关系对象的创建细节
/*** 实例工厂方法: 实例工厂的方法, 即需要创建工厂本身, 在调用工厂的实例方法来返回 bean 的实例*/
public class InstanceCarFactory {private Map cars = null;public InstanceCarFactory() {cars = new HashMap<>();cars.put("audi", new Car("audi", "xixi", 20000));cars.put("ford", new Car("ford", "hha", 30000));}public Car getCar(String name) {return cars.get(name);}
}
配置 Bean:
factory-bean
:指向实例工厂方法的 Bean
factory-method
:指向实例工厂方法的名字
constructor-arg
:如果工厂方法需要传入参数, 则用 constructor-arg 来配置参数
结果:
Car [brand=ford, corp=hha, price=30000.0]
2.1.4 实现 FactoryBean 接口配置 Bean
getObject
方法所返回的对象//自定义的 FactoryBean 需要实现 FactoryBean 接口
public class CarFactoryBean implements FactoryBean{private String brand;public void setBrand(String brand) {this.brand = brand;}//返回 Bean 的对象@Overridepublic Car getObject() throws Exception {return new Car(brand, 500000);}//返回 Bean 的类型@Overridepublic Class> getObjectType() {return Car.class;}@Overridepublic boolean isSingleton() {return true;}
}
配置 Bean:
通过 FactoryBean
来配置 Bean 的实例
class
:指向 FactoryBean
的全类名
property
:配置 FactoryBean
的属性
但实际返回的实例却是 FactoryBean 的 getObject()
方法返回的实例
结果:
Car [brand=audi, price=500000.0]
在Spring IOC 容器读取 Bean 配置创建 Bean 实例之前,必须对它进行实例化。只有在容器实例化之后,才可以从 IOC 容器里获取 Bean 实例并使用。Spring 提供了两种类型的 IOC 容器实现
BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身
ApplicationContext 面向使用 Spring 框架的开发者,几乎所有应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
public class Main {public static void main(String[] args) {//1. 创建 Spring 得 IOC 容器对象//ApplicationContext 代笔 IOC 容器//ClassPathXmlApplicationContext: 是 ApplicationContext 接口的实现类, 该实现类从类路径下来加载配置文件.ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");//2. 对 IOC 容器中获取 Bean 实例//利用 id 定位到 IOC 容器中的 beanHelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld2");//利用类型返回 IOC 容器中的 Bean, 但要求 IOC 容器中必须只能有一个该类型的 Bean
// HelloWorld helloWorld = ctx.getBean(HelloWorld.class);System.out.println(helloWorld);// //3. 调用方法
// helloWorld.hello();}
}
**属性注入:**即通过 setter 方法注入 Bean 的属性值或依赖的对象。属性注入是实际应用中最常用的注入方式
字面值: 可用字符串表示的值,可以通过
元素标签或 value="nihao"
属性进行注入。
PS: 若字面值中包含特殊字符,可以使用 把字面值包裹
引用其他 Bean: 在 Bean 的配置文件中,可以通过 元素或者 ref 属性为 Bean 的属性或者构造器参数指定对 Bean 的引用
内部 Bean: 内部 Bean 声明直接包含在
或者
元素里,不需要设置任何 id 或 name 属性。同时内部 Bean 不能使用在其他任何地方
集合属性: 在 Spring 中可以通过一组内置的 xml 标签,如
、
、
root password jdbc:mysql:///test com.mysql.jdbc.Driver
使用utility scheme定义集合
使用基本的集合标签定义集合时,不能将集合作为独立的 Bean 定义,导致其他 Bean 无法引用该集合,所以无法在不同 Bean 直接共享集合
使用 p 命名空间
Spring IOC 容器可自动装配 Bean,需要做的仅仅是在
的 autowire 属性里指定自动装配的模式
可以使用 autowire 属性指定 自动装配 的方式.
byName: 根据 bean 的名字(id 的 值)和当前 bean 的 setter 风格的属性名进行自动装配,若有匹配的,则进行自动装配,若没有匹配的,则不装配
byType: 根据 bean 的类型和当前 bean 的属性的类型进行自动装配,若 IOC 容器中有 1 个以上的类型匹配的 bean,则抛出异常
缺点: 如果只希望装配个别属性时, autowire 就不够灵活,autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之。在实际项目中很少使用自动装配功能, 因为和自动装配功能所带来的好处比起来, 明确清晰的配置文档更加具有说服力
的 abstract 属性为 true
Spring 可以在
元素的 scope 属性里设置 Bean 的作用域
db.properties:
user=root
password=lwh011305
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/fileupload?useSSL=true
导入属性文件:
类似于 EL:SpEL 使用 #{...}
作为定界符,所以在大框号中的字符被认为是 SpEL
为属性赋一个字面量:
使用 SpEL 引用类的静态属性:
使用 SpEL 来引用其他 Bean
30000 ? '金领' : '白领'}">
Spring IOC 容器对 Bean 的生命周期进行管理的过程:
创建 Bean 方法
public class Car {public Car() {System.out.println("Car's Constructor ... ");}private String brand;public void setBrand(String brand) {System.out.println("setBrand ... ");this.brand = brand;}public String getBrand() {return brand;}public void init() {System.out.println("init ... ");}public void destory() {System.out.println("destroy ... ");}@Overridepublic String toString() {return "Car [brand=" + brand + "]";}
}
为 Bean 设置属性值:init-method
和 destory-method
属性为 Bean 指定初始化和销毁方法
调用 Bean 的初始化方法
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-cycle.xml");Car car = (Car) ctx.getBean("car1");
System.out.println(car);ctx.close();
输出:
Car's Constructor ...
setBrand ...
init ...
Car [brand=Audi]
六月 28, 2018 5:24:15 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@6438a396: startup date [Thu Jun 28 17:24:14 CST 2018]; root of context hierarchy
destroy ...
创建 Bean 的后置处理器
BeanPostProcessor
接口Spring IOC 容器对 Bean 的生命周期进行管理的过程:
postProcessBeforeInitialization
方法postProcessAfterInitialization
方法实现 BeanPostProcessor 接口:
bean: bean 实例本身
beanName: IOC 容器配置的 bean 的名字.
返回值: 是实际上返回给用户的那个 Bean,注意:可以在以上两个方法中修改返回的 Bean,甚至返回一个新的 Bean
public Object postProcessBeforeInitialization(Object bean, String beanName)
:init-method 之前被调用
public Object postProcessAfterInitialization(Object bean, String beanName)
:init-method 之后被调用的实现
public class MyBeanPostProcessor implements BeanPostProcessor{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization: " + bean + ", " + beanName);if("car".equals(beanName)) {//..}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization: " + bean + ", " + beanName);Car car = new Car();car.setBrand("Ford");return car;}
}
配置 Bean
输出:
Car's Constructor ...
setBrand ...
postProcessBeforeInitialization: Car [brand=Audi], car1
init ...
postProcessAfterInitialization: Car [brand=Audi], car1
Car's Constructor ...
setBrand ...
Car [brand=Ford]
六月 28, 2018 5:53:28 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@6438a396: startup date [Thu Jun 28 17:53:27 CST 2018]; root of context hierarchy
destroy ...
泛型依赖注入:子类之间的依赖关系由其父类泛型以及父类之间的依赖关系来确定,父类的泛型必须为同一类型
BaseRepository 类
public class BaseRepository {}
*UserRepository 类:*标识持久层
@Repository
public class UserRepository extends BaseRepository{}
BaseService 类: 通过 Autowired
自动装配 BaseRepository
实例
public class BaseService {@Autowiredprotected BaseRepository repository;public void add() {System.out.println("add ...");System.out.println(repository);}}
UserService 类: 通过父类的泛型实例,在 UserService
中已经注入了 UserRepository
实例
@Service
public class UserService extends BaseService{}
输出:
add ...
edu.just.spring.beans.generic.di.UserRepository@799d4f69
下一篇:redis集群模式登陆