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());
}
总结
给容器中注册组件方法;
- 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
- @Bean[导入的第三方包里面的组件]
- @Import[快速给容器中导入一个组件]
3.1 @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
3.2 ImportSelector:返回需要导入的组件的全类名数组
3.3 ImportBeanDefinitionRegistrar:手动注册bean到容器中 - 使用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]