spring注解详解
@PropertySource
用来将properties文件中的K/V值加入到运行时变量中
@PropertySource(value = {"classpath:/person.properties"})
@Scope
@Bean
@Scope("singleton")//单例模式
public Car car(){
return new Car();
}
@ComponentScan
会扫描该类所在的包及其子包的所有类,条件匹配则加入ioc容器中,默认将带注解的类加入到ioc容器中
可以定义多个@Filter规则
1.基本用法
1.当没有指定ComponentScan注解的扫描规则,就会以扫描该配置类所在的包及其子包,来完成组件的注册
2.扫描要注入的组件,扫描@Component,@Controller,@service,和@Repository
等同于xml中的 <context:component-scan base-package="com.atguigu">
package com.zhw.bean.config;
@Configuration
@ComponentScan(value={"com.zhw"},excludeFilters = {@Filter(type = FilterType.ANNOTATION,classes = { Service.class})})
//includeFilters:只包含的内容
@ComponentScan(value={"com.zhw"},includeFilters = {@Filter(type = FilterType.ANNOTATION,classes = {Controller.class})},useDefaultFilters = false)
//value:指定要扫描的包
//excludeFilters:要排除的内容 type = FilterType.ANNOTATION 按照什么规则排除,注解 classes = {Controller.class, Service.class} 排除哪些注解
public class BeansConfig {
}
2.自定规则
package com.zhw.bean.config;
import java.io.IOException;
public class MyTypeFilter implements TypeFilter {
/**
* 当扫到每一个类都会执行该类的match方法
* @param metadataReader 读取到的当前正在扫描的类的信息
* @param metadataReaderFactory 可以获取到其他任何类信息的
* @return
* @throws IOException
*/
@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("Dao")){
return true;
}
return false;
}
}
package com.zhw.bean.config;
@Configuration
//会扫描com.zhw包下的所有组件类,只注册满足要求的类
@ComponentScans(value = {
@ComponentScan(value={"com.zhw"},includeFilters = {
@Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},
useDefaultFilters = false)})
@Repository
public class BeansConfig {
}
componentScan会扫描所指定的包以及子包的所有类,按照所给定的规则进行注入
3.@ComponentScans
可以定义多个@ComponentScan
package com.zhw.bean.config;
@Configuration
@ComponentScans({@ComponentScan(basePackages = {"com.zhw.bean.book"})})
public class MainConfigOfAutowired {
@Primary
@Bean("bookDaoImpl2")
public BookDaoImpl bookDaoImpl(){
return new BookDaoImpl("2");
}
}
1.懒加载 @Lazy
对于单实例的bean,默认在容器启动的时候创建对象,
懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化
2.@Configuration
说明该类是一个配置类,等同于 一个xml文件
package com.zhw.bean.config;
import com.zhw.bean.entities.Person;
import com.zhw.bean.service.PersonService;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
@Configuration
//@ComponentScan(value={"com.zhw"},excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = { Service.class})})
//@ComponentScan(value={"com.zhw"},includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})},useDefaultFilters = false)
//value:指定要扫描的包
//excludeFilters:要排除的内容 type = FilterType.ANNOTATION 按照什么规则排除,注解 classes = {Controller.class, Service.class} 排除哪些注解
@ComponentScans(value = {
@ComponentScan(value={"com.zhw"},includeFilters = {
// @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
// @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {PersonService.class}),
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},
useDefaultFilters = false)})
public class BeansConfig {
}
3.按条件装配 @Condition
我把你加入到容器中,但是如果该类有一个@Condition注解则需要满足我的条件我才会注入
@Conditional:按照一定的条件进行判断,满足条件给容器中注册bean,可以用在方法和类上
@Bean("bill") @Conditional({WindowsCondition.class}) public Person person01() { return new Person("bill",62); } @Bean("linus") @Conditional(value = {LinuxCondition.class}) public Person person02() { return new Person("linus",46); }
需要出入Condition的实现类
/** * 判断是否是linux系统 */
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("linux")){
return true;
}
return false;
}
}
package com.zhw.bean.condition;
public class WindowsCondition implements Condition {
/**
* 判断是否windows系统
* @param conditionContext 判断条件能使用的上下文环境
* @param annotatedTypeMetadata 注释信息
* @return
* */
* @Override
* public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata)
//1.获取到ioc使用的beanfactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//2.获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//3.获取当前的环境信息
Environment environment = conditionContext.getEnvironment();
//4.获取到bean定义的注册类,可以用他的方法注册,删除,查询bean的定义
BeanDefinitionRegistry registry = conditionContext.getRegistry();
String property = environment.getProperty("os.name");
//判断容器中是否包含某个组件
boolean zsh = registry.containsBeanDefinition("zsh");
if (property.contains("Windows") ){
return true;
}
return false;
}
}
package com.zhw.bean.config;import com.zhw.bean.condition.LinuxCondition;import com.zhw.bean.condition.WindowsCondition;import com.zhw.bean.entities.Person;import com.zhw.bean.entities.Student;import org.springframework.context.annotation.*;@Configuration@Conditional(value = {WindowsCondition.class}) //满足这个条件,这个类中配置的所有bean注册才能生效public class MainConfig { //懒加载 @Bean @Lazy public Person person() { return new Person("bil",62); } @Bean("bill") @Conditional({WindowsCondition.class}) public Person person01() { return new Person("bill",62); } @Bean("linus") @Conditional(value = {LinuxCondition.class}) public Person person02() { return new Person("linus",46); } @Bean("zsh") public Student studnt() { return new Student("12","zsh"); }}
4.@Import
给容器中注册组件
1).包扫描+组件注解标注(@Controller/@Service/@Repository/@Component)
2).@Bean[导入的第三方包里面的组件]
3).@Import快速给容器中导入组件
1.基础用法
直接写这个组件的class类型(要导入的组件),容器中就会自动注册这个组件,id默认为全类名
@Configuration
@Import(value = {Student.class,Person.class})
public class MainConfig2 {}
2.高级用法@ImportSelector
ImportSelector:返回需要导入组件的全类名
定义引导类
package com.zhw.bean.condition;
/**
* 返回值就是要导入的组件
**/
public class MySelectImports implements ImportSelector {
/**
* @param annotationMetadata 当前标注@Import注解的类的所有注解信息
* @return 返回的是类的全限定名,就会注入到ioc容器中
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//用
//annotationMetadata.
//方法可以返回空数组,但是不能是null
String[] strings = new String[3];
strings[0] = "com.zhw.bean.entities.Color";
return strings;
}
}
package com.zhw.bean.config;
@Configuration
@Import(value = {Student.class,Person.class,MySelectImports.class})
public class MainConfig2 {}
3.@ImportBeanDefinitionRegistrar
@ImportBeanDefinitionRegistrar
//定义实现类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param annotationMetadata 可以获取标注import的所有注解信息 * @param beanDefinitionRegistry BeanDefinition注册类
* 把所有需要添加到容器中的bean,可以调用beanDefinitionRegistry的方法
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
//获取容器中的Student
boolean student = beanDefinitionRegistry.containsBeanDefinition("com.zhw.bean.entities.Student");
//获取容器中的Person
boolean person = beanDefinitionRegistry.containsBeanDefinition("com.zhw.bean.entities.Person");
if (student && person) {
//定义bean的信息
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Yelloow.class);
//参数一:bean的id
beanDefinitionRegistry.registerBeanDefinition("Yellow",rootBeanDefinition);
}
}
}
//引入
package com.zhw.bean.config;
@Configuration@Import(value = {Student.class,Person.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {}
结果:
5.FactoryBean(工厂bean)
1.定义factory工厂
package com.zhw.bean.config;
import com.zhw.bean.entities.Color;
import org.springframework.beans.factory.FactoryBean;
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean {
//返回一个Color对象,这个对象会添加到容器中
@Override
public Object getObject() throws Exception {
return new Color();
}
//返回对象的类型
@Override
public Class<?> getObjectType() {
return Color.class;
}
/**
* 设置是否是单实例
* @return true 单实例 ,false 多实例
*/
@Override
public boolean isSingleton() {
return true;
}
}
2.引入factorybean工厂
package com.zhw.bean.config;import com.zhw.bean.entities.Color;import com.zhw.bean.entities.Person;import com.zhw.bean.entities.Student;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;@Configuration@Import({ColorFactoryBean.class})public class MainConfig3 {}
3.测试
@Test @SuppressWarnings("resource") public void Test05() { seeBeans(); Object bean1 = app.getBean("com.zhw.bean.config.ColorFactoryBean"); Object bean2 = app.getBean("com.zhw.bean.config.ColorFactoryBean"); System.out.println(bean1.getClass()); //获取factorybean工厂 Object bean = app.getBean("&com.zhw.bean.config.ColorFactoryBean"); System.out.println(bean+"工厂bean"); //多实例 System.out.println(bean1 == bean2); }
4.结果
5.注意
工厂类其实质是Color对象,拿到factorybean对象是加一个前缀“&”就得到啦
6.bean生命周期
1.用@Bean注解指定初始化和销毁方法
bean创建–>初始化–>销毁过程
package com.zhw.bean.config;import com.zhw.bean.entities.Car;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import org.springframework.context.annotation.Scope;/** * bean的生命周期 * bean创建-->初始化 -->销毁 * 容器管理单实例bean的生命周期: * 可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法 * 构造(对象创建) * 单实例:在容器启动的时候创建 * 多实例:在每次获取的时候创建对象 * 初始化: * 对象创建完成,并赋值好,调用初始化方法。。。 * 销毁: * 容器关闭的时候,执行销毁的方法 * * 1).指定初始化和销毁的方法 * init-method和destory-method */@Configurationpublic class MainConfigOfLifeCycle { @Bean(initMethod = "init",destroyMethod = "destory") @Scope("singleton") public Car car() { return new Car(); }}
对于多实例的bean,只有获取该bean的时候才会创建,执行其初始化的方法,并且容器关闭也不会执行销毁方法
2.通过让Bean实现接口指定初始化和销毁方法
@Componentpublic class Cat implements InitializingBean, DisposableBean { public Cat() { System.out.println("constructor...cat..."); } //销毁方法 @Override public void destroy() throws Exception { System.out.println("cat...destory"); } //初始化方法 @Override public void afterPropertiesSet() throws Exception { System.out.println("cat...init"); }}
3.使用JSR250
1.@PostConstruct:在bean创建完成并且属性赋值完成,执行初始化
2.@PreDestory:在bean在容器销毁之前
package com.zhw.bean.entities;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;@Component //加入到容器中public class Dog { public Dog() { System.out.println("dog..constructor.."); } //对象创建 的方法 @PostConstruct public void init() { System.out.println("PostConstructor..."); } //对象在容器关闭之前的方法 @PreDestroy public void destory() { System.out.println("PreDestory..."); }}
4.BeanPostProcessor-后置处理器
针对组件中的所有组件的初始化前后
在bean初始化前后处理一些工作:
package com.zhw.bean.entities;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor { public MyBeanPostProcessor() { System.out.println("constructor..."); } /** * 在初始化之前工作 * @param o bean对象 * @param s bean的名字 * @return * @throws BeansException */ @Override public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("postProcessBeforeInitialization"+s+o+"初始化之前"); return o; } /** * 在初始化之后工作 * @param o * @param s * @return * @throws BeansException */ @Override public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("postProcessAfterInitialization"+s+o+"初始化之后"); return o; }}
属性赋值相关的注解
1.@value:在实体类中写
1.写配置文件
2.引入配置文件
3.用@Value(${“”})
person.nickNmae=小刺老
package com.zhw.bean.config;@Configuration//使用@PropertySource读取外部配置文件中的k/v值保存到运行的环境变量,加载完外部的配置文件以后使用${}取出配置文件的值@PropertySource(value = {"classpath:/person.properties"})public class MainConfigOfProperty { @Bean public Person person() { return new Person(); }}
@Data@NoArgsConstructor@AllArgsConstructorpublic class Person { //使用@Value赋值 //1.基本数值 //2.可以写SpEL,#{} //3.可以写${},取出配置文件的值(在运行环境变量里面的值) @Value("张三") private String name; @Value("#{10*2}") private Integer age; @Value("${person.nickName}") private String nickName;}
//属性相关的注解测试//可以使用app获取运行数据 @Test @SuppressWarnings("resource") public void Test07() { seeBeans(); Person bean = app.getBean(Person.class); System.out.println(bean); ConfigurableEnvironment environment = app.getEnvironment(); String property = environment.getProperty("person.nickName"); Map<String, Object> systemProperties = environment.getSystemProperties(); systemProperties.forEach((S,O) -> System.out.println(S + O)); }
自动装配
1.@AutoWired
Controller注入Service,Service注入Dao,
1).@Autowired:自动注入按照类型注入
优先按照类型去容器中找对应的组件:app.getBean(BookDao.class)
@Servicepublic class BookServiceImpl implements BookService { @Autowired private BookDao bookDao;}当像容器内其中注入多个相同类型的组件时会报错,注入时会报错,可以使用@Primary注解指定当冲突的时候优先使用带有@primary注解的类
@AutoWired不仅可以标注在属性上,话可以构造器,参数,方法上
1.标注在方法位置上
package com.zhw.bean.boos;@Componentpublic class Boos { private Car car; public Car getCar() { return car; } @Autowired //标注在,spring容器创建当前对象,就会调用方法,完成赋值 //方法使用的参数,从ioc容器中获取 public void setCar(Car car) { this.car = car; }}
package com.zhw.bean.boos;import org.springframework.stereotype.Component;@Componentpublic class Car {}
@Test public void test07() {// see2(); Boos bean = app2.getBean(Boos.class); Car car = bean.getCar(); Car bean1 = app2.getBean(Car.class); System.out.println(bean1); System.out.println(car); }
2.标注在有参构造器上
package com.zhw.bean.boos;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;//默认加载ioc容器中的组件,容器启动会调用组建的无参构造器创建对象,在进行初始化赋值等操作,也就是说,容器一启动,就会创建容器中包含的所有组件@Componentpublic class Boos { private Car car; public Car getCar() { return car; } //当容器启动调用,有参构造器方法,并且找到从容器中找Car组件,并且注入 @Autowired public Boos(Car car){ this.car = car; } public void setCar(Car car) { this.car = car; }}
3.标注在参数上
package com.zhw.bean.boos;@Componentpublic class Boos { private Car car; public Car getCar() { return car; } //从容器中获组件,如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是会从容器中获取 public Boos(@Autowired Car car){ this.car = car; } public void setCar(Car car) { this.car = car; }}
@Bean//会从容器中获取carpublic Boos boos( @Autowired Car car ) { Color color = new Color(); color.setCar(car); return color;}
其本质就是根据类型,从容器中找到指定的组件注入
2.@Qualifier(“name”)
@Qualifier:按照名称 注入,需要结合@Autowired使用
@Service@Datapublic class BookServiceImpl implements BookService { @Autowired //按照类型注入,有多个类型相同会报错 @Qualifier("bookDaoImpl2") //按照名称注入 private BookDaoImpl bookDaoImpl2; @Override public void print(){ System.out.println(bookDaoImpl2); }}
@Service@Datapublic class BookServiceImpl implements BookService { //按照id当required = false时没有找到也不会报错 @Autowired(required = false) @Qualifier("bookDaoImpl2") private BookDaoImpl bookDaoImpl2; @Override public void print(){ System.out.println(bookDaoImpl2); }}
3.@Primary
让Spring进行自动装配的时候,默认使用首选的bean
//容器中可能有多个相同类型的bean,首先使用带有@Primary注解的bean@Configuration@ComponentScans({@ComponentScan(basePackages = {"com.zhw.bean.book"})})public class MainConfigOfAutowired { @Primary @Bean("bookDaoImpl2") public BookDaoImpl bookDaoImpl(){ return new BookDaoImpl("2"); }}
@Test public void test05() { BookServiceImpl bookService = app.getBean(BookServiceImpl.class); BookDaoImpl bookDaoImpl2 = bookService.getBookDaoImpl2(); System.out.println(bookDaoImpl2.getLable()); }
@Repositorypublic class BookDaoImpl implements BookDao { public BookDaoImpl() { } public BookDaoImpl(String lable) { this.lable = lable; } private String lable = "1"; public String getLable() { return lable; } public void setLable(String lable) { this.lable = lable; }}
注入了带有@primary注解的bean
4.@Resource(JSR250)[java规范的注解]
@Resource:java规范和@AutoWired一样默认按照属性的名臣装配的
@Service@Datapublic class BookServiceImpl implements BookService {// @Autowired(required = false) //按照类型注入,有多个类型相同会报错// @Qualifier("bookDaoImpl2")// private BookDaoImpl bookDaoImpl2;// @Autowired //按照类型注入,有多个类型相同会报错 @Resource(name = "bookDao",type = BookDao.class") private BookDaoImpl bookDaoImpl; //注入指定名称的bean 找不到会报错 @Resource(name = "bookDaoImpl2") private BookDaoImpl bookDaoImpl; @Override public void print(){ System.out.println(bookDaoImpl); }}
1.找不到bean name=""会报错
5.@Inject(JSR250)[java规范的注解]
1.和@Autowried一样保留@Primary的特性@Service@Datapublic class BookServiceImpl implements BookService {// @Autowired(required = false) //按照类型注入,有多个类型相同会报错// @Qualifier("bookDaoImpl2")// private BookDaoImpl bookDaoImpl2;// @Autowired //按照类型注入,有多个类型相同会报错// @Resource(name = "bookDaoImpl2") @Inject private BookDaoImpl bookDaoImpl; @Override public void print(){ System.out.println(bookDaoImpl); }}
需要导入@inject的jar包
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
6.自定义组件使用Spring容器底层的组件
自定义组件实现xxxAware:在创建对象的时候,会调用接口规定的方法注入相关的组件,把spring底层一些组件注入到自定i的Bean中;
xxxAware:功能使用XXXProcessor;
ApplicationContextAware ==> ApplicationContextAwareProcessor
package com.zhw.bean.component;@Componentpublic class Component1 implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware { private ApplicationContext applicationContext; public ApplicationContext getApplicationContext() { return applicationContext; } //设置ioc容器对象 @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("传入的ioc:"+applicationContext); this.applicationContext = applicationContext; } //当前组件的名称id @Override public void setBeanName(String s) { System.out.println("当前bean的名字'':\""+s); } @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { String s = resolver.resolveStringValue("你好${os.name},我是#{20*10}"); System.out.println(s); }}
@Testpublic void test() { Component1 component = app.getBean(Component1.class); ApplicationContext app = component.getApplicationContext();}
@Profile
1.spring为我们提供的可以根据当前环境,动态的切换和激活一系列组件的功能
2.指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
3.加了环境标识,只有该环境激活了才注入,默认是default环境
package com.zhw.bean.config;@Configuration@PropertySource("classpath:/db.properties")public class MainConfigOfProfile implements EmbeddedValueResolverAware { @Value("${jdbc.url}") private String url; @Value("${jdbc.password}") private String password; @Value("${jdbc.user}") private String user; private String driver; private StringValueResolver resolver; @Profile("test") @Bean("TestDataSource") public DataSource dataSourceTest() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Bean @Profile("test") public Car car(){ return new Car(); } //默认环境,不加也是默认环境 @Profile("default") @Bean("DefaultDataSource") public DataSource dataSourceDefault() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Profile("dev") @Bean("DevDataSource") public DataSource dataSourceDev() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Profile("pro") @Bean("ProDataSource") public DataSource dataSourcePro() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { this.resolver = resolver; this.driver = resolver.resolveStringValue("${jdbc.driver}"); }}
1.使用代码的方式指定环境
package com.zhw.test;public class IOCTest_Profile { @Test public void test01(){ //创建ApplicationContext对象 AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(); //设置需要激活的环境 app.getEnvironment().setActiveProfiles("test","dev"); //注册主配置类 app.register(MainConfigOfProfile.class); //刷新容器 app.refresh(); String[] beanDefinitionNames = app.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { System.out.println(beanDefinitionName); } }}
2.写在类上
package com.zhw.bean.config;@Configuration@PropertySource("classpath:/db.properties")@Profile("pro") //只有是指定的环境才会加载该配置类public class MainConfigOfProfile implements EmbeddedValueResolverAware { @Value("${jdbc.url}") private String url; @Value("${jdbc.password}") private String password; @Value("${jdbc.user}") private String user; private String driver; private StringValueResolver resolver; @Profile("test") @Bean("TestDataSource") public DataSource dataSourceTest() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Bean @Profile("test") public Car car(){ return new Car(); } //默认环境,不加也是默认环境 @Profile("default") @Bean("DefaultDataSource") public DataSource dataSourceDefault() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Profile("dev") @Bean("DevDataSource") public DataSource dataSourceDev() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Profile("pro") @Bean("ProDataSource") public DataSource dataSourcePro() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { this.resolver = resolver; this.driver = resolver.resolveStringValue("${jdbc.driver}"); }}
注意点:
没有标识环境的Bean在任何环境下都是加载的
AOP[动态代理]
1.使用
值在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的变成方式:
1.目标类
package com.zhw.aop;public class MathCalculator { public int div(int x,int y){ return x/y; }}
2.切面类
package com.zhw.aop;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.*;import java.util.Arrays;import java.util.List;@Aspectpublic class LogAspects { //抽入公共的切入点表达式 //1. 本类引用 @Pointcut("execution(public int com.zhw.aop.MathCalculator.*(..))") public void pointCut(){};// @Before在目标方法之前切入,切入点表达式(指定在哪个方法切入) @Before("pointCut()") public void logStart(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); List<Object> objects = Arrays.asList(args); System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+objects+"}"); } @After("pointCut()") public void logEnd(JoinPoint joinPoint){ System.out.println(""+joinPoint.getSignature().getName()+"结束"); } @AfterReturning(value = "pointCut()",returning = "result") public void logReturn(Object result){ //封装返回值 System.out.println("方法正常返回。。运行结果:{"+result+"}"); } @AfterThrowing(value = "pointCut()",throwing = "e") public void logException(JoinPoint joinPoint,Exception e) { //封装异常 JoinPoint必须写在参数的第一个位置 System.out.println("除法异常。。。异常信息:{"+e.getLocalizedMessage()+"}"); }}
3.配置类
package com.zhw.aop;@EnableAspectJAutoProxy // 一定要开启注解的AOP@Configurationpublic class MainConfigOfAOP { //目标类 @Bean public MathCalculator calculator(){ return new MathCalculator(); } //切面类 @Bean public LogAspects aspects(){ return new LogAspects(); }}
步骤
1.写业务类
2.写切面类
3.加入到容器
4.开启注解AOP
5.测试
2.原理
1.@EnableAspectJAutoProxy
package org.springframework.context.annotation;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AspectJAutoProxyRegistrar.class) //导入组件,利用AspectJAutoProxyRegistrar自定义给容器中注册beanpublic @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false; boolean exposeProxy() default false;}