spring学习_part1

Spring作用

容器

管理bean生命周期、bean之间依赖关系。

Ioc

控制反转。将bean对象的管理交由Spring容器管理。原理是通过反射。

DI

依赖注入。解决对象之间的依赖关系。
Spring利用依赖注入(DI)完成对IOC容器中各个组件的依赖关系赋值。

AOP

面向切面编程,将日志、事务等业务抽离理解成切面,和业务逻辑解耦开。

配置方式初始化bean

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>${spring.version}</version>
</dependency>
<bean id="person" class="com.sss.bean.Person" scope="prototype" >
	<property name="age" value="12"></property>
	<property name="name" value="zhangsan"></property>
</bean>
public class ConfigTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Person bean = (Person) applicationContext.getBean("person");
        System.out.println(bean);
    }
}
Person [name=zhangsan, age=12, nickName=null]

注解方式获取bean

@Configuration
public class MainConfig {
    @Bean("person")
    public Person person01() {
        return new Person("lisi", 20);
    }
}
public class Test2 {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);

        String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
        for (String name : namesForType) {
            System.out.println(name);
        }
    }
}
Person [name=lisi, age=20, nickName=null]
person

ApplicationContext

构造ApplicationContext可以通过

ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");

ApplicationContext ac = new FileSystemXmlApplicationContext("beans.xml");

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));

此种方式,bean的初始化是在真正使用时候才创建的。

构造方法

ioc容器的bean,默认会调用无参构造方法创建对象。

如果将构造方法设置为private

/**
 * 天鹅
 */
@Component
public class Swan {
    private String name;

    private Swan(){
        
    }

    public Swan(String name) {
        this.name = name;
    }
}

@ComponentScan("com.sss.bean.poultry")
@Configuration
public class MainConfig5 {

}
@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig5.class);
	System.out.println("容器创建完成...");
	Object swan = applicationContext.getBean("swan");
	System.out.println(swan);
	System.out.println("容器关闭");
	applicationContext.close();
}
容器创建完成...
com.sss.bean.poultry.Swan@7d3a22a9
容器关闭

如果没有无参构造方法

/**
 * 天鹅
 */
@Component
public class Swan {
    private String name;

    public Swan(String name) {
        this.name = name;
    }
}
@ComponentScan("com.sss.bean.poultry")
@Configuration
public class MainConfig5 {

}
@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig5.class);
	System.out.println("容器创建完成...");
	Object swan = applicationContext.getBean("swan");
	System.out.println(swan);
	System.out.println("容器关闭");
	applicationContext.close();
}
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'swan' defined in file [D:\github_projects\spring_core\spring-annotation\target\classes\com\sss\bean\poultry\Swan.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'swan' defined in file [D:\xxx\target\classes\com\sss\bean\poultry\Swan.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1341)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1187)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
	at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
	at com.sss.test.Test5.test01(Test5.java:13)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1658)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1217)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1171)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
	... 36 more


Process finished with exit code -1

包扫描

xml配置包扫描用:

<context:property-placeholder location="classpath:person.properties"/>

注解包扫描用:

@Configuration
@ComponentScan("com.sss.controller,com.sss.service")
public class MainConfig {
    @Bean("person")
    public Person person01() {
        return new Person("lisi", 20);
    }
}
package com.sss.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.sss.service.BookService;

@Controller
public class BookController {
	@Autowired
	private BookService bookService;
}

package com.sss.service;
import org.springframework.stereotype.Service;

@Service
public class BookService {
	
}
package com.sss.dao;

import org.springframework.stereotype.Repository;

@Repository
public class BookDao {
	
	private String lable = "1";

	public String getLable() {
		return lable;
	}

	public void setLable(String lable) {
		this.lable = lable;
	}

	@Override
	public String toString() {
		return "BookDao [lable=" + lable + "]";
	}
}
@SuppressWarnings("resource")
@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
	String[] definitionNames = applicationContext.getBeanDefinitionNames();
	for (String name : definitionNames) {
		System.out.println(name);
	}
}
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookService
person

bookDao并没有纳入扫描包下。

@ComponentScan(value="com.atguigu",includeFilters = {@Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})},useDefaultFilters = false)	})
excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照给定的类型;
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:使用正则表达式指定
FilterType.CUSTOM:使用自定义规则

MyTypeFilter类

import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

public class MyTypeFilter implements TypeFilter {

	/**
	 * metadataReader:读取到的当前正在扫描的类的信息
	 * metadataReaderFactory:可以获取到其他任何类信息的
	 */
	@Override
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		// TODO Auto-generated method stub
		//获取当前类注解的信息
		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		//获取当前正在扫描的类的类信息
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		//获取当前类资源(类的路径)
		Resource resource = metadataReader.getResource();
		
		String className = classMetadata.getClassName();
		System.out.println("--->"+className);
		if(className.contains("er")){
			return true;
		}
		return false;
	}
}

作用域@Scope

public class MainConfig2 {
	@Scope("singleton")
	@Bean("person")
	public Person person(){
		return new Person("张三", 25);
	}
}
@Test
public void test02(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	Object bean = applicationContext.getBean("person");
	Object bean2 = applicationContext.getBean("person");
	System.out.println(bean == bean2);
}
true

@Scope默认是单实例的,如果改成@Scope(“prototype”):

false

prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器,每次获取的时候才会调用方法创建对象。
singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿。
request:同一次请求创建一个实例。
session:同一个session创建一个实例。

如果@Scope是singleton,以下代码会输出:


@Scope("singleton")
@Bean("person")
public Person person(){
	System.out.println("向Ioc容器添加Person");
	return new Person("张三", 25);
}
@Test
public void test02(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	System.out.println("Ioc容器创建完成");
	Object bean = applicationContext.getBean("person");
	Object bean2 = applicationContext.getBean("person");
	System.out.println(bean == bean2);
}
向Ioc容器添加Person
Ioc容器创建完成
true

如果@Scope是prototype,以下代码会输出:

@Scope("prototype")
@Bean("person")
public Person person(){
	System.out.println("向Ioc容器添加Person");
	return new Person("张三", 25);
}
@Test
public void test02(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	System.out.println("Ioc容器创建完成");
	Object bean = applicationContext.getBean("person");
	Object bean2 = applicationContext.getBean("person");
	System.out.println(bean == bean2);
}
Ioc容器创建完成
向Ioc容器添加Person
向Ioc容器添加Person
false

懒加载

IOC容器启动的时候,先不创建bean,第一次使用的时候再创建bean

@Test
public void test03(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	System.out.println("Ioc容器创建完成");
}
向Ioc容器添加Person
Ioc容器创建完成

但是如果加上了Lazy:

@Scope("singleton")
@Bean("person")
@Lazy
public Person person(){
	System.out.println("向Ioc容器添加Person");
	return new Person("张三", 25);
}

@Test
public void test02(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	System.out.println("Ioc容器创建完成");
}
Ioc容器创建完成
@Test
public void test02(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	System.out.println("Ioc容器创建完成");
	Object bean = applicationContext.getBean("person");
	Object bean2 = applicationContext.getBean("person");
	System.out.println(bean == bean2);
}
Ioc容器创建完成
向Ioc容器添加Person
true

Conditional按照一定条件判断

如果没有Conditional,会打印bill和linus两个人。

@Bean("bill")
public Person person01(){
	return new Person("Bill Gates",62);
}

@Bean("linus")
public Person person02(){
	return new Person("linus", 48);
}
@Test
public void test03(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
	for (String name : namesForType) {
		System.out.println(name);
	}
}
person
bill
linus

如果想根据当前系统类型,动态构造bean

package com.sss.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

//判断是否linux系统
public class LinuxCondition implements Condition {
	/**
	 * ConditionContext:判断条件能使用的上下文(环境)
	 * AnnotatedTypeMetadata:注释信息
	 */
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO是否linux系统
		//1、能获取到ioc使用的beanfactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		//2、获取类加载器
		ClassLoader classLoader = context.getClassLoader();
		//3、获取当前环境信息
		Environment environment = context.getEnvironment();
		//4、获取到bean定义的注册类
		BeanDefinitionRegistry registry = context.getRegistry();
		
		String property = environment.getProperty("os.name");
		
		//可以判断容器中的bean注册情况,也可以给容器中注册bean
		boolean definition = registry.containsBeanDefinition("person");
		if(property.contains("linux")){
			return true;
		}
		return false;
	}
}

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

//判断是否windows系统
public class WindowsCondition implements Condition {
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		Environment environment = context.getEnvironment();
		String property = environment.getProperty("os.name");
		if(property.contains("Windows")){
			return true;
		}
		return false;
	}
}

@Test
public void test04(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
	ConfigurableEnvironment environment = applicationContext.getEnvironment();
	//动态获取环境变量的值;Windows 10
	String property = environment.getProperty("os.name");
	System.out.println(property);
	for (String name : namesForType) {
		System.out.println(name);
	}
	Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
	System.out.println(persons);
}
/**
 * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
 *
 * 如果系统是windows,给容器中注册("bill")
 * 如果是linux系统,给容器中注册("linus")
 */
@Bean("bill")
@Conditional(WindowsCondition.class)
public Person person01(){
	return new Person("Bill Gates",62);
}

@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person02(){
	return new Person("linus", 48);
}
Windows 10
person
bill
向Ioc容器添加Person
{person=Person [name=张三, age=25, nickName=null], bill=Person [name=Bill Gates, age=62, nickName=null]}

@Import导入组件

直接导入class

package com.sss.bean;

public class Dog {
    private String name;
    private int age;
    //getter setter constructor
}

@Import(Dog.class)
public class MainConfig3 {

}
@Test
public void test5(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
	printBeans(applicationContext);
}

private void printBeans(AnnotationConfigApplicationContext applicationContext){
	String[] definitionNames = applicationContext.getBeanDefinitionNames();
	for (String name : definitionNames) {
		System.out.println(name);
	}
}
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig3
com.sss.bean.Dog

ImportSelector

package com.sss.bean;

public class Dog {
    private String name;
    private int age;
    //getter setter constructor
}

package com.sss.bean;

public class Cat {
    private String name;
    private int age;
    //getter setter constructor
}

//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
	//返回值,就是到导入到容器中的组件全类名
	//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		//importingClassMetadata
		//方法不要返回null值
		return new String[]{"com.sss.bean.Dog","com.sss.bean.Cat"};
	}
}

@Import({MyImportSelector.class})
public class MainConfig3 {

}
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig3
com.sss.bean.Dog
com.sss.bean.Cat

ImportBeanDefinitionRegistrar

手动注册bean到容器中

@Import({MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig3 {
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * AnnotationMetadata:当前类的注解信息
	 * BeanDefinitionRegistry:BeanDefinition注册类;
	 * 		把所有需要添加到容器中的bean;调用
	 * 		BeanDefinitionRegistry.registerBeanDefinition手工注册进来
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
		boolean definition = registry.containsBeanDefinition("com.sss.bean.Dog");
		boolean definition2 = registry.containsBeanDefinition("com.sss.bean.Cat");
		if(definition && definition2){
			//指定Bean定义信息;(Bean的类型,Bean。。。)
			RootBeanDefinition beanDefinition = new RootBeanDefinition(AnimalFood.class);
			//注册一个Bean,指定bean名
			registry.registerBeanDefinition("animalFood", beanDefinition);
		}
	}

}

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig3
com.sss.bean.Dog
com.sss.bean.Cat
animalFood

FactoryBean

@ComponentScan("com.sss.pac11")
@Configuration
public class Config11 {
	
}
@Component
public class ServiceFactory implements FactoryBean<StudentService> {
    @Override
    public StudentService getObject() throws Exception {
        return new StudentServiceImpl();
    }

    @Override
    public Class<?> getObjectType() {
        return StudentService.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
public interface StudentService {
}
@Component
public class StudentServiceImpl implements StudentService {
}
@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext =
            new AnnotationConfigApplicationContext(Config11.class);
    ServiceFactory fac1 = applicationContext.getBean(ServiceFactory.class);
    ServiceFactory fac2 = applicationContext.getBean(ServiceFactory.class);
    System.out.println(fac1 == fac2);

    Object bean4 = applicationContext.getBean("&serviceFactory");
    System.out.println(bean4.getClass());
}

总结

给容器中注册组件方法;

  1. 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
  2. @Bean[导入的第三方包里面的组件]
  3. @Import[快速给容器中导入一个组件]
    3.1 @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
    3.2 ImportSelector:返回需要导入的组件的全类名数组
    3.3 ImportBeanDefinitionRegistrar:手动注册bean到容器中
  4. 使用Spring提供的 FactoryBean(工厂Bean);
    4.1 默认获取到的是工厂bean调用getObject创建的对象
    4.2 要获取工厂Bean本身,我们需要给id前面加一个&

@Bean指定初始化和销毁方法

方法一:指定bean的init和destroy方法

public class Duck {
    public Duck(){
        System.out.println("duck constructor");
    }
    
    public void init(){
        System.out.println("duck init");
    }
    
    public void destroy(){
        System.out.println("duck destory");
    }
}
@ComponentScan("com.sss.bean")
@Configuration
public class MainConfig4 {

	@Bean(initMethod="init",destroyMethod="destroy")
	public Duck duck(){
		return new Duck();
	}
}
@Test
public void test01(){
	//1、创建ioc容器
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig4.class);
	System.out.println("容器创建完成...");
	//applicationContext.getBean("duck");
	//关闭容器
	System.out.println("容器关闭");
	applicationContext.close();
}
duck constructor
duck init
容器创建完成...
容器关闭
duck destory

如果修改Scope=prototype

@ComponentScan("com.sss.bean")
@Configuration
public class MainConfig4 {

	@Scope("prototype")
	@Bean(initMethod="init",destroyMethod="destroy")
	public Duck duck(){
		return new Duck();
	}
}
@Test
public void test01(){
	//1、创建ioc容器
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig4.class);
	System.out.println("容器创建完成...");
	//applicationContext.getBean("duck");
	//关闭容器
	System.out.println("容器关闭");
	applicationContext.close();
}
容器创建完成...
容器关闭

@Test
public void test01(){
	//1、创建ioc容器
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig4.class);
	System.out.println("容器创建完成...");
	applicationContext.getBean("duck");
	//关闭容器
	System.out.println("容器关闭");
	applicationContext.close();
}
容器创建完成...
duck constructor
duck init
容器关闭

如果不是单例,IOC容器不会帮忙销毁bean

方法二:InitializingBean和DisposableBean接口

@Component
public class Horse implements InitializingBean, DisposableBean {
    public Horse(){
        System.out.println("构造方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("销毁");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet");
    }
}

@ComponentScan("com.sss.bean")
@Configuration
public class MainConfig4 {

}
构造方法
afterPropertiesSet
容器创建完成...
容器关闭
销毁

方法三:

可以使用JSR250;
@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作

@Component
public class Deer {
    public Deer(){
        System.out.println("鹿的构造方法");
    }

    @PostConstruct
    public void init(){
        System.out.println("鹿PostConstruct");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("鹿PreDstroy");
    }
}
@ComponentScan("com.sss.bean")
@Configuration
public class MainConfig4 {
}
@Test
public void test02(){
	//1、创建ioc容器
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig4.class);
	System.out.println("容器创建完成...");
	//关闭容器
	System.out.println("容器关闭");
	applicationContext.close();
}
鹿的构造方法
鹿PostConstruct
容器创建完成...
容器关闭
鹿PreDstroy

方法四:BeanPostProcessor

BeanPostProcessor是bean后置处理器,bean创建对象初始化前后进行拦截。

在bean初始化前后进行一些处理工作:
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作

package com.sss.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 后置处理器:初始化前后进行处理工作
 * 将后置处理器加入到容器中
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
		return bean;
	}

}

@Test
public void test02(){
	//1、创建ioc容器
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig4.class);
	System.out.println("容器创建完成...");
	//关闭容器
	System.out.println("容器关闭");
	applicationContext.close();
}
postProcessBeforeInitialization...mainConfig4=>com.sss.config.MainConfig4$$EnhancerBySpringCGLIB$$7af6db39@fdefd3f
postProcessAfterInitialization...mainConfig4=>com.sss.config.MainConfig4$$EnhancerBySpringCGLIB$$7af6db39@fdefd3f
鹿的构造方法
postProcessBeforeInitialization...deer=>com.sss.bean.Deer@8909f18
鹿PostConstruct
postProcessAfterInitialization...deer=>com.sss.bean.Deer@8909f18
容器创建完成...
容器关闭
鹿PreDstroy

bean属性赋值

简单属性赋值

package com.sss.bean.pac6;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Pig {
    @Value("佩奇")
    private String name;

    @Value("#{20-2}")
    private int age;

    public Pig() {
    }

    //getter setter方法有没有都行。

    @Override
    public String toString() {
        return "Pig{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

@ComponentScan("com.sss.bean.pac6")
@Configuration
public class MainConfig6 {

}
@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig6.class);
	System.out.println("容器创建完成...");
	Object pig = applicationContext.getBean("pig");
	System.out.println(pig);
	System.out.println("容器关闭");
	applicationContext.close();
}
容器创建完成...
Pig{name='佩奇', age=18}
容器关闭

属性值放配置文件里

@Component
public class Pig {
    //@Value("佩奇")
    @Value("${name}")
    private String name;

    //@Value("#{20-2}")
    @Value("${age}")
    private int age;

    public Pig() {
    }

    @Override
    public String toString() {
        return "Pig{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
@ComponentScan("com.sss.bean.pac6")
@PropertySource(value={"classpath:/pac6/pig.properties"})
@Configuration
public class MainConfig6 {

}
@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig6.class);
	System.out.println("容器创建完成...");
	Object pig = applicationContext.getBean("pig");
	System.out.println(pig);
	System.out.println("容器关闭");
	applicationContext.close();
}
容器创建完成...
Pig{name='乔治', age=18}
容器关闭

Autowired

Autowired默认优先按照类型去容器中找对应的组件。applicationContext.getBean(BookDao.class),如果找到多个类型相同的bean,再根据bean的id去容器中寻找:applicationContext.getBean(“bookDao”)。或者通过@Qualifier(“bookDao”)指定bean的id。

如果容器里有多个id相同的bean,报错。

@Autowired自动装配的bean,如果ioc容器找不到指定的bean,报错。
当然也可以通过设置required=false指定,如果ioc容器找不到指定的bean,就不装配。

@Service
public class BookService{
    @Qualifier("bookDao")
    @Autowired(required=false)
    private BookDao bookDao;
}

@Autowired注解如果标注在方法上,ioc容器创建对象时,会调用该方法完成赋值。

ioc容器的bean,默认会调用无参构造方法创建对象。可以将@Autowired标注在构造方法上指定初始化对象的方法。

@Component
public class StudentController {
    private StudentService studentService;

    public StudentService getStudentService() {
        return studentService;
    }

    @Autowired
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }

    @Override
    public String toString() {
        return "StudentController{" +
                "studentService=" + studentService +
                '}';
    }
}
@Component
public class StudentService {
}
@ComponentScan("com.sss.pac7")
@Configuration
public class MainConfig7 {

}
@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig7.class);
	System.out.println("容器创建完成...");

	StudentController controller = applicationContext.getBean(StudentController.class);
	System.out.println(controller);

	StudentService service = applicationContext.getBean(StudentService.class);
	System.out.println(service);

	System.out.println(controller.getStudentService() == service);

	System.out.println("容器关闭");
	applicationContext.close();
}
容器创建完成...
StudentController{studentService=com.sss.pac7.StudentService@54c562f7}
com.sss.pac7.StudentService@54c562f7
true
容器关闭

profile

英文单词意思:侧写、外形、轮廓、人物简介

package com.sss.pac8;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfig8 {

    @Value("${db.user}")
    private String username;

    @Value("${db.password}")
    private String password;

    @Value("${db.jdbcUrl}")
    private String jdbcUrl;

    @Value("${db.driverClass}")
    private String driverClass;

    @Bean
    public DataSource dataSourceDev() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(username);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }

    @Bean
    public DataSource dataSourceTest() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(username);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }
}
db.username=root
db.password=password
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://localhost:3306/test
@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig8.class);
	System.out.println("容器创建完成...");
	String[] dataSources = applicationContext.getBeanNamesForType(DataSource.class);
	System.out.println(Arrays.asList(dataSources));
}
容器创建完成...
[dataSourceDev, dataSourceTest]

启动命令加了以下内容后:

-Dspring.profiles.active=test

同时添加@Profile注解:

@Profile("dev")
@Bean
public DataSource dataSourceDev() throws PropertyVetoException {
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setUser(username);
    dataSource.setPassword(password);
    dataSource.setJdbcUrl(jdbcUrl);
    dataSource.setDriverClass(driverClass);
    return dataSource;
}

@Profile("test")
@Bean
public DataSource dataSourceTest() throws PropertyVetoException {
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setUser(username);
    dataSource.setPassword(password);
    dataSource.setJdbcUrl(jdbcUrl);
    dataSource.setDriverClass(driverClass);
    return dataSource;
}
容器创建完成...
[dataSourceTest]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值