目录
方式7:使用实现类ImportBeanDefinitionRegistrar
ImportSelector和ImportBeanDefinitionRegistrar区别:
方式8:实现类BeanDefinitionRegistryPostProcessor
方式1: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">
<!--xml声明自定义bean-->
<bean id="cat" class="com.itheima.bean.Cat"/>
<bean class="com.itheima.bean.Dog"/>
<!--xml声明第三方bean-->
<bean id="druidBean" class="com.alibaba.druid.pool.DruidDataSource"/>
</beans>
public class App1 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
方式2:注解+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: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-->
<context:component-scan base-package="com.itheima.bean,com.itheima.config"/>
</beans>
package com.itheima.bean;
import org.springframework.stereotype.Component;
@Component("Tom")
public class Cat {
}
package com.itheima.app;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
方式3:纯注解方式:
package com.itheima.config;
import org.springframework.context.annotation.ComponentScan;
// 使用配置类方式获取bean时,可以省略@Component或@Configuration
// 当被其他类扫描加载bean时,例如:创建配置类获取第三方bean。不能省略@Component或@Configuration
@ComponentScan({"com.itheima.bean","com.itheima.config"})
public class SpringConfig3 {
}
package com.itheima.app;
import com.itheima.config.SpringConfig3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App3 {
public static void main(String[] args) {
//使用配置类方式获取bean时,会自动创建配置类的bean
//同DbConfig一样只有创建bean之后,才能获取内部的bean
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig3.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
FactoryBean方式
package com.itheima.bean;
import org.springframework.beans.factory.FactoryBean;
//泛型中指明使用工厂类创建bean的类型
public class DogFactoryBean implements FactoryBean<Dog> {
//返回对象
public Dog getObject() throws Exception {
Dog dog = new Dog();
return dog;
}
//返回类型
public Class<?> getObjectType() {
return Dog.class;
}
//是否单例(true 单例 false 非单例)
public boolean isSingleton() {
return false;
}
}
package com.itheima.config;
import com.itheima.bean.DogFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
// 使用配置类方式获取bean时,可以省略@Component或@Configuration。就可以获取到自身类bean和内部定义的bean
// 当被其他类扫描加载bean时,例如:创建配置类DbConfig获取第三方bean数据源Druid。不能省略@Component或@Configuration,必须被容器扫描到才能加载到自身和内部定义的bean
@ComponentScan({"com.itheima.bean","com.itheima.config"})
public class SpringConfig3 {
//使用实现接口FactoryBean<T>创建出来的是泛型中的bean
@Bean
public DogFactoryBean dog(){
DogFactoryBean dogFactoryBean = new DogFactoryBean();
return dogFactoryBean;
}
}
public class App3 {
public static void main(String[] args) {
//使用配置类方式获取bean时,会自动创建配置类的bean
//同DbConfig一样只有创建bean之后,才能获取内部的bean
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig3.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
System.out.println(context.getBean(Dog.class));
System.out.println(context.getBean(Dog.class));
System.out.println(context.getBean(Dog.class));
}
}
通过factoryBean创建的是泛型中的bean对象,单例模式内存地址相同
proxyBeanMethods属性
package com.itheima.config;
import com.itheima.bean.Cat;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//proxyBeanMethods,默认值true,使用CGLIB方式创建动态代理对象。false,输出对象内存地址
// 使用此注解保证此类内部创建的所有bean都是同一个对象
@Configuration(proxyBeanMethods = true)
public class SpringConfig33 {
@Bean
public Cat cat(){
Cat cat = new Cat();
return cat;
}
}
package com.itheima.app;
import com.itheima.config.SpringConfig33;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App33 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig33.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
System.out.println("----------------");
SpringConfig33 springConfig33 = context.getBean(SpringConfig33.class);
System.out.println(springConfig33);
System.out.println(springConfig33.cat());
System.out.println(springConfig33.cat());
System.out.println(springConfig33.cat());
}
}
保证自身类中内部bean的唯一性
@ImportResource注解
package com.itheima.config;
import org.springframework.context.annotation.ImportResource;
//将原始xml配置文件中信息,迁移到注解配置类中使用。便于后期把原始项目的xml方式变更为注解方式开发
@ImportResource({"applicationContext1.xml","applicationContext12.xml"})
public class SpringConfig32 {
}
方式4:@Import方式:
package com.itheima.bean;
public class Dog {
}
package com.itheima.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class DbConfig {
@Bean
public DruidDataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
}
package com.itheima.config;
import com.itheima.bean.Dog;
import org.springframework.context.annotation.Import;
//使用@Import导入bean直接使用类名.class即可,无需使用@Component等注解定义bean,便于spring解耦操作
@Import({Dog.class,DbConfig.class})
public class SpringConfig4 {
}
可以使用Import注入配置类,注入的配置类无需将自身类定义为bean,当做一个普通类即可
特点:使用import注入bean直接使用类名.class就可以把普通类加载为bean
方式5:手工加载bean
package com.itheima.bean;
import org.springframework.stereotype.Component;
@Component("Tom")
public class Cat {
private String name;
public Cat() {
}
public Cat(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
package com.itheima.app;
import com.itheima.bean.Cat;
import com.itheima.config.SpringConfig4;
import com.itheima.config.SpringConfig5;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App5 {
public static void main(String[] args) {
//必须使用ApplicationContext接口,实现类AnnotationConfigApplicationContext才能手动加载bean
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig5.class);
//spring容器初始化完毕后,手工加载bean
//同时加载同一个bean,后加载会覆盖之前加载的bean
context.registerBean("cat", Cat.class,"cat1");
context.registerBean("cat", Cat.class,"cat2");
context.registerBean("cat", Cat.class,"cat3");
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
System.out.println(context.getBean(Cat.class));
}
}
方式6:使用实现类ImportSelector
package com.itheima.bean;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.Map;
public class MyImportSelector implements ImportSelector {
//通过各种判定决定具体加载哪些bean
//Metadata元数据
public String[] selectImports(AnnotationMetadata metadata) {
//hasAnnotation判断当前元数据类是否使用了指定注解,导入注解的全路径名
boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Configuration");
//获取元数据类中指定注解中的所有属性值
//当前为查看@ComponentScan注解中的所有属性
Map<String, Object> attributes = metadata.getAnnotationAttributes("org.springframework.context.annotation.ComponentScan");
System.out.println("---------------------");
System.out.println(attributes);
System.out.println("---------------------");
//对是否加载bean做出判断
if (flag){
return new String[]{
"com.itheima.bean.Cat"
};
}else {
return new String[]{
"com.itheima.bean.Dog"
};
}
}
}
元数据类:
package com.itheima.config;
import com.itheima.bean.MyImportSelector;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
//通过导入ImportSelector接口的实现类加载bean
//ImportSelector导入在哪个位置当前位置就是元数据类
@Import(MyImportSelector.class)
@Configuration
@ComponentScan(basePackages = {"com.itheima.bean"})
public class SpringConfig6 {
}
方式7:使用实现类ImportBeanDefinitionRegistrar
package com.itheima.bean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata
, BeanDefinitionRegistry registry) {
//获取bean的字节码文件
BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();
//使用bean名称生成器指定bean的名称
//需要指定bean的名称和字节码文件
registry.registerBeanDefinition("Spike",beanDefinition);
}
}
package com.itheima.config;
import com.itheima.bean.MyRegistrar;
import org.springframework.context.annotation.Import;
@Import(MyRegistrar.class)
public class SpringConfig7 {
}
ImportSelector和ImportBeanDefinitionRegistrar区别:
ImportSelector:元数据全路径名生成bean。
ImportBeanDefinitionRegistrar:使用BeanDefiniton指定定类的class文件和bean名称生成bean
方式8:实现类BeanDefinitionRegistryPostProcessor
package com.itheima.bean.service.impl;
import com.itheima.bean.service.BookService;
import org.springframework.stereotype.Service;
@Service("BookService")
public class BookServiceImpl1 implements BookService {
public void check() {
System.out.println("book Service 1..");
}
}
BookService模拟了4个实现类,每个方法调用check都是都是输出book Service n...
如:BookServiceImpl1输出book Service 1..
BookServiceImpl2输出book Service 2..
......
package com.itheima.bean;
import com.itheima.bean.service.impl.BookServiceImpl2;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyRegistrar2 implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata
, BeanDefinitionRegistry registry) {
//获取bean的字节码文件
BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl2.class).getBeanDefinition();
//使用bean名称生成器:指定bean的名称、bean的字节码文件
registry.registerBeanDefinition("BookService",beanDefinition);
}
}
package com.itheima.bean;
import com.itheima.bean.service.impl.BookServiceImpl3;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyRegistrar3 implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata
, BeanDefinitionRegistry registry) {
//获取bean的字节码文件
BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl3.class).getBeanDefinition();
//使用bean名称生成器:指定bean的名称、bean的字节码文件
registry.registerBeanDefinition("BookService",beanDefinition);
}
}
package com.itheima.bean;
import com.itheima.bean.service.impl.BookServiceImpl4;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//获取bean的字节码文件
BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl4.class).getBeanDefinition();
//使用bean名称生成器:指定bean的名称、bean的字节码文件
registry.registerBeanDefinition("BookService",beanDefinition);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
package com.itheima.config;
import com.itheima.bean.MyPostProcessor;
import com.itheima.bean.MyRegistrar2;
import com.itheima.bean.MyRegistrar3;
import com.itheima.bean.service.impl.BookServiceImpl1;
import org.springframework.context.annotation.Import;
@Import({BookServiceImpl1.class,MyPostProcessor.class,MyRegistrar3.class,MyRegistrar2.class})
public class SpringConfig8 {
}
使用@import方式导入上面四种创建bean
package com.itheima.app;
import com.itheima.bean.service.BookService;
import com.itheima.config.SpringConfig8;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App8 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig8.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
BookService bookService = (BookService) context.getBean("BookService");
bookService.check();
}
}
通过4种不同的方式创建BookService的bean,并调用当中的同一个方法。
观察调用的结果