<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu</groupId>
<artifactId>spring-annotation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
</dependencies>
</project>
package com.atguigu.bean;
public class Person {
private String name;
private Integer age;
public Person() {
super();
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<bean id="person" class="com.atguigu.bean.Person">
<property name="age" value="18"></property>
<property name="name" value="zhangsan"></property>
</bean>
</beans>
package com.atguigu;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.atguigu.bean.Person;
import com.atguigu.config.MainConfig;
public class MainTest {
@SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Person person = (Person)applicationContext.getBean("person");
System.out.println(person);
}
}
package com.atguigu.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.atguigu.bean.Person;
/**
* 配置类
* 等同于以前的配置文件
*/
@Configuration //告诉Spring这是一个配置类
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,id默认是用方法名作为id
@Bean
public Person person() {
return new Person("lisi",20);
}
}
package com.atguigu;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.atguigu.bean.Person;
import com.atguigu.config.MainConfig;
public class MainTest {
public static void main(String[] args) {
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
// Person person = (Person)applicationContext.getBean("person");
// System.out.println(person);
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
}
}
@Bean(“person02”) 还可以为Bean的类型名取名
以前的xml扫描
<!-- 包扫描、只要标注了@Controller、@Service、@Repository,@Component -->
<context:component-scan base-package="com.atguigu"></context:component-scan>
等同于注解
@ComponentScan(value = "com.atguigu")
package com.atguigu.controller;
import org.springframework.stereotype.Controller;
@Controller
public class BookController {
}
package com.atguigu.dao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDao {
}
package com.atguigu.service;
import org.springframework.stereotype.Service;
@Service
public class BookService {
}
package com.atguigu.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import com.atguigu.bean.Person;
/**
* 配置类
* 等同于以前的配置文件
*/
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu")
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,id默认是用方法名作为id
@Bean
public Person person() {
return new Person("lisi",20);
}
}
package com.atguigu.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.config.MainConfig;
public class IOCTest {
@SuppressWarnings("resource")
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
例如使用ANNOTATION
package com.atguigu.config;
import java.security.Provider.Service;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import com.atguigu.bean.Person;
/**
* 配置类
* 等同于以前的配置文件
*/
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",excludeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})
})
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,id默认是用方法名作为id
@Bean
public Person person() {
return new Person("lisi",20);
}
}
以前在xml中必须配置禁用默认的过滤规则
<!-- 包扫描、只要标注了@Controller、@Service、@Repository,@Component -->
<context:component-scan base-package="com.atguigu" use-default-filters="false"></context:component-scan>
注解
useDefaultFilters = false
package com.atguigu.config;
import java.security.Provider.Service;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import com.atguigu.bean.Person;
/**
* 配置类
* 等同于以前的配置文件
*/
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",includeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
},useDefaultFilters = false)
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,id默认是用方法名作为id
@Bean
public Person person() {
return new Person("lisi",20);
}
}
@ComponentScans(
value = {@ComponentScan(value = "com.atguigu",includeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
},useDefaultFilters = false)
}
)
@ComponentScans(
value = {@ComponentScan(value = "com.atguigu",includeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class})
},useDefaultFilters = false)
}
)
@ComponentScans(
value = {@ComponentScan(value = "com.atguigu",includeFilters = {
@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
},useDefaultFilters = false)
}
)
package com.atguigu.config;
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 {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(例如类的路径)
Resource resource = metadataReader.getResource();
//类名
String className = classMetadata.getClassName();
System.out.println("--->"+className);
return false;
}
}
只要当前处理到哪个类,类的信息都可以获取的到
获取到这些类的信息,我们就可以做判断,满足条件的返回true.
package com.atguigu.config;
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 {
//获取当前类注解的信息
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;
}
}
package com.atguigu.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.atguigu.bean.Person;
@Configuration
public class MainConfig2 {
@Bean("person")
public Person person() {
return new Person("张三",25);
}
}
package com.atguigu.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.config.MainConfig2;
public class IOCTest {
@SuppressWarnings("resource")
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
Object bean = applicationContext.getBean("person");
Object bean2 = applicationContext.getBean("person");
//输出一下,两个对象是否相等
System.out.println(bean == bean2);
}
}
参数:
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Person;
@Configuration
public class MainConfig2 {
//默认是单实例的
/**
* ConfigurableBeanFactory#SCOPE_PROTOTYPE prototype
* ConfigurableBeanFactory#SCOPE_SINGLETON singleton
* org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
* org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session
*
* prototype: 多实例的
* singleton: 单实例的(默认值)
* request: 同一次请求创建一个实例
* session: 同一个session创建一个实例
* @return
*/
@Scope("prototype")
@Bean("person")
public Person person() {
return new Person("张三",25);
}
}
懒加载:
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Person;
@Configuration
public class MainConfig2 {
//默认是单实例的
/**
* @Scope
* ConfigurableBeanFactory#SCOPE_PROTOTYPE prototype
* ConfigurableBeanFactory#SCOPE_SINGLETON singleton
* org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
* org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session
* prototype: 多实例的
* singleton: 单实例的(默认值)
* request: 同一次请求创建一个实例
* session: 同一个session创建一个实例
*
* @return
*
* @Lazy懒加载
*/
@Lazy
@Bean("person")
public Person person() {
return new Person("张三",25);
}
}
@Conditional({Condition}): 按照一定的条件进行判断,满足条件给容器中注册bean
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Person;
import com.atguigu.condition.LinuxCondition;
import com.atguigu.condition.WindowsCondition;
@Configuration
public class MainConfig2 {
/**
* @Conditional({Condition}): 按照一定的条件进行判断,满足条件给容器中注册bean
*
* 如果系统是windows ,给容器中注册("bill")
* 如果系统是linux ,给容器中注册("linux")
*/
@Conditional({WindowsCondition.class})
@Bean("bill")
public Person person01() {
return new Person("Bill Gates",62);
}
@Conditional({LinuxCondition.class})
@Bean("linux")
public Person person02() {
return new Person("linux",48);
}
}
@Conditional需要Condition类来判断
package com.atguigu.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;
//判断系统是否是Windows
public class WindowsCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 是否Windows系统
//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");
if(property.contains("Windows")) {
return true;
}
return false;
}
}
package com.atguigu.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) {
// 是否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");
if(property.contains("linux")) {
return true;
}
return false;
}
}
package com.atguigu.test;
import java.util.Map;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.atguigu.bean.Person;
import com.atguigu.config.MainConfig2;
public class IOCTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
@Test
public void test01() {
String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//动态获取环境变量的值
String property = environment.getProperty("os.name");
System.out.println(property);
for (String name : beanNamesForType) {
System.out.println(name);
}
Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
System.out.println(persons);
}
}
再试试Linux,当然我不可能切换操作系统
我们改变一个运行时变量。
不仅可以加在方法上 ,也可以加在类上。
给容器中注册组件
容器中就会自动注册这个组件,id默认是全类名
package com.atguigu.bean;
public class Color {
}
package com.atguigu.bean;
public class Red {
}
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Color;
import com.atguigu.bean.Person;
import com.atguigu.bean.Red;
import com.atguigu.condition.LinuxCondition;
import com.atguigu.condition.WindowsCondition;
@Configuration
@Import(Color.class) //导入组件,id默认是组件的全类名
public class MainConfig2 {
}
package com.atguigu.test;
import java.util.Map;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.atguigu.bean.Person;
import com.atguigu.config.MainConfig2;
public class IOCTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
@Test
public void testImport() {
printBeans(applicationContext);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext) {
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Color;
import com.atguigu.bean.Person;
import com.atguigu.bean.Red;
import com.atguigu.condition.LinuxCondition;
import com.atguigu.condition.WindowsCondition;
@Configuration
//@Import(Color.class) //导入组件,id默认是组件的全类名
@Import({Color.class,Red.class}) //导入多个组件
public class MainConfig2 {
}
ImportSelector: 返回需要导入的组件的全类名数组
package com.atguigu.bean;
public class Blue {
}
package com.atguigu.bean;
public class Yellow {
}
package com.atguigu.condition;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector{
//返回值,就是要导入到容器中的组件全类名
//AnnotationMetadata: 当前标注@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// TODO Auto-generated method stub
// importingClassMetadata.get //可以获取了所有注解的信息和所有跟类有关的信息
//不要返回null值,可以返回空数组new String[]{};
return new String[] {"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
}
}
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Color;
import com.atguigu.bean.Person;
import com.atguigu.bean.Red;
import com.atguigu.condition.LinuxCondition;
import com.atguigu.condition.MyImportSelector;
import com.atguigu.condition.WindowsCondition;
@Configuration
//@Import(Color.class) //导入组件,id默认是组件的全类名
@Import({Color.class,Red.class,MyImportSelector.class}) //导入多个组件
public class MainConfig2 {
}
package com.atguigu.test;
import java.util.Map;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.atguigu.bean.Person;
import com.atguigu.config.MainConfig2;
public class IOCTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
@Test
public void testImport() {
printBeans(applicationContext);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext) {
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
package com.atguigu.condition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import com.atguigu.bean.RainBow;
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{
/**
* AnnotationMetadata: 当前类的注解信息以及其他的信息
* BeanDefinitionRegistry: BeanDefinition注册类
* 把所有中需要添加到容器中的bean;
* BeanDefinitionRegistry.registerBeanDefinition(手动注册进来)
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
if(definition && definition2) {
//指定bean名
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
registry.registerBeanDefinition("rainBow", rootBeanDefinition);
}
}
}
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Color;
import com.atguigu.bean.Person;
import com.atguigu.bean.Red;
import com.atguigu.condition.LinuxCondition;
import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
import com.atguigu.condition.MyImportSelector;
import com.atguigu.condition.WindowsCondition;
@Configuration
//@Import(Color.class) //导入组件,id默认是组件的全类名
@Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class}) //导入多个组件
public class MainConfig2 {
}
package com.atguigu.test;
import java.util.Map;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.atguigu.bean.Person;
import com.atguigu.config.MainConfig2;
public class IOCTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
@Test
public void testImport() {
printBeans(applicationContext);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext) {
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
package com.atguigu.bean;
import org.springframework.beans.factory.FactoryBean;
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color>{
//返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
System.out.println("ColorFactoryBean...getgetObject....");
return new Color();
}
@Override
public Class<?> getObjectType() {
System.out.println("ColorFactoryBean...getObjectType....");
return Color.class;
}
//控制是否是单例
//true:这个bean是单实例,在容器中保存一份
//false: 多实例,每次获取都会创建一个新的bean
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return true;
}
}
package com.atguigu.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.atguigu.bean.Color;
import com.atguigu.bean.ColorFactoryBean;
import com.atguigu.bean.Person;
import com.atguigu.bean.Red;
import com.atguigu.condition.LinuxCondition;
import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
import com.atguigu.condition.MyImportSelector;
import com.atguigu.condition.WindowsCondition;
@Configuration
//@Import(Color.class) //导入组件,id默认是组件的全类名
@Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class}) //导入多个组件
public class MainConfig2 {
@Bean
public ColorFactoryBean colorFactoryBean() {
return new ColorFactoryBean();
}
}
package com.atguigu.test;
import java.util.Map;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.atguigu.bean.Person;
import com.atguigu.config.MainConfig2;
public class IOCTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
@Test
public void testImport() {
printBeans(applicationContext);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext) {
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");
Object colorFactoryBean2 = applicationContext.getBean("colorFactoryBean");
System.out.println("colorFactoryBean的类型:"+colorFactoryBean.getClass());
System.out.println(colorFactoryBean == colorFactoryBean2);
//通过在前面加上& Spring就知道我们是需要工厂bean的本身
Object colorFactoryBean3 = applicationContext.getBean("&colorFactoryBean");
System.out.println("&colorFactoryBean的类型:"+colorFactoryBean3.getClass());
}
}
指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
package com.atguigu.aop;
/**
* 数学计算器
* @author john
*
*/
public class MathCalculator {
//除法
public int div(int i,int j) {
System.out.println("MathCalculator..........div");
return i/j;
}
}
我们需要在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常)
切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行
通知方法:
并且必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
package com.atguigu.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* 切面类
*
* @Aspect: 告诉Spring当前类是一个切面类
* @author john
*
*/
@Aspect
public class LogAspects {
//抽取公共的切入点表达式
//1.如果在本类引用:("pointCut()")
//2.如果引用其他的切面类:必须用方法全名("com.atguigu.aop.LogAspects.pointCut()")
//写法参照Spring官方文档
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut() {}
//@Before:在目标方法之前切入 ; 切入点表达式(指定在哪个方法切入)
//使用目标方法全名
// @Before("public int com.atguigu.aop.MathCalculator.div(int, int)")
//任意方法,任意多参数
// @Before("public int com.atguigu.aop.MathCalculator.*(..)")
//抽取公共的切入点表达式
@Before("pointCut()")
public void logStart(JoinPoint joinPoint) {
//获取的方法的方法名: joinPoint.getSignature().getName()
//获取的方法的参数: joinPoint.getArgs()
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。参数列表是:{"+Arrays.asList(args)+"}");
}
//@After: 在目标方法之后;切入无论方法正常结束或者异常结束都执行
// @After("public int com.atguigu.aop.MathCalculator.*(..)")
//抽取公共的切入点表达式
@After("pointCut()")
public void logEnd(JoinPoint joinPoint) {
System.out.println(""+joinPoint.getSignature().getName()+"结束");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
并且给配置类中加@EnableAspectJAutoProxy 【开启基于注解的aop模式】
package com.atguigu.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.atguigu.aop.LogAspects;
import com.atguigu.aop.MathCalculator;
/**
* AOP:【动态代理】
* 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
* 1、导入aop模块;Spring AOP :(spring-aspects)
* 2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常)
* 3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
* 通知方法:
* 前置通知(@Before):logStart: 在目标方法(div)运行之前运行
* 后置通知(@After):logEnd: 在目标方法(div)运行结束之后运行
* 返回通知(@AfterReturning):logReturn: 在目标方法div正常返回之后运行
* 异常通知(@AfterThrowing):logException: 在目标方法(div)出现异常以后运行
* 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
* 4、给切面类的目标方法标注何时何地运行(通知注解);并且必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
* 5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
* 6、给配置类中加@EnableAspectJAutoProxy 【开启基于注解的aop模式】
* 在
*/
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
//业务逻辑类加入容器中
@Bean
public MathCalculator calculator() {
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects() {
return new LogAspects();
}
}
package com.atguigu.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.aop.MathCalculator;
import com.atguigu.config.MainConfigOfAOP;
import com.atguigu.dao.BookDao;
import com.atguigu.service.BookService;
public class IOCTest_AOP {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
//1、不要自己创建对象
// MathCalculator mathCalculator = new MathCalculator();
// mathCalculator.div(1, 1);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
System.out.println("-----------------------正常测试------------------------");
//正常测试
mathCalculator.div(1, 1);
System.out.println("-----------------------异常测试------------------------");
//异常测试
mathCalculator.div(1, 0);
applicationContext.close();
}
}