Spring注解开发
1. IOC相关注解
1.1 @Configuration
从Spring3.0
,@Configuration
用于定义配置类,可替换xml
配置文件,被注解的类内部包含有一个或多个被@Bean
注解的方法,这些方法将会被AnnotationConfigApplicationContext
或AnnotationConfigWebApplicationContext
类进行扫描,并用于构建bean
定义,初始化Spring
容器。
注意:@Configuration
注解的配置类有如下要求:
-
@Configuration不可以是
final
类型; -
@Configuration不可以是匿名类;
-
嵌套的configuration必须是静态类。
@Configration注解同时被
@Component注解修饰,因此具有被自动加载的特点,被@Configuration修饰的类本身也会作为definition注册。
value属性是Configuration bean名称。
@Configuration //@Configuration 相当于applicationContext.xml配置文件
public class AppConfig {
}
public class SpringTest {
//可以通过new AnnotationConfigApplicationContext(参数为@Configuration注解的类的class)
@Test
public void test1(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(applicationContext);
}
}
1.2 @Bean
可以注解在方法上,容器会根据注解生成一个Bean对象。
1.3 @ComponentScan
作用在类上,声明需要对包路径下资源进行扫描,效果等同于<context:component-scan>
可以在一个类上多次使用@ComponentScan或者使用@ComponentScans注解,@ComponentScans可以包含多个@ComponentScan注解。
- value: 属性指定要扫描的包路径,多个用逗号分割
- excludeFilters:指定扫描的时候按照什么规则排除哪些组件。规则在@Filter中设置
- includeFilters:指定扫描的时候只需要包含哪些组件。
- useDefaultFilters:是否使用默认的规则。默认值true。
- @ComponentScan.Filter:设置过滤规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H5VyE4OJ-1583204877986)(D:\TyporaDate\Spring\images\ComponentScan.png)]
//扫描
@ComponentScan(value="com.zm")
//设置排除规则
@ComponentScan(value = "com.zm",excludeFilters = {
@ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class})
})
//设置包含规则,和useDefaultFilters一起使用排除默认的组件
@ComponentScan(value = "com.zm",includeFilters = {
@ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class})
},useDefaultFilters = false)
@ComponentScan.Filter:
type:属性值为FilterType枚举类型的值。默认值为ANNOTATION
- ANNOTATION: 注解类型,配合AnnotationTypeFilter使用,筛选出被指定注解修饰的资源
- ASSIGNABLE_TYPE: 枚举出扫描类型,配合AssignableTypeFilter使用,加载指定类型的资源(含子类)
- ASPECTJ: 用AspectJ表达式匹配资源。
- REGEX: Java正则匹配资源
- CUSTOM: 自定义的FIlter
classes:配合type一起使用,当type为
- ANNOTATION:待扫描注解
- ASSIGNABLE_TYPE:用户枚举的类
- CUSTOM:自定义Filter
自定义Filter过滤规则
1.编写一个类,实现TypeFilter接口,在实现方法中定义Filtergui规则
public class MyTypeFilter implements TypeFilter {
/**
* MetadataReader metadataReader:获取当前正在扫描的类的信息
* MetadataReaderFactory metadataReaderFactory,获取带其他任何类的信息
*
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();//获取当前类的注解信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();//获取当前扫描的类信息
Resource resource = metadataReader.getResource();//获取当前扫描的资源信息
String name = classMetadata.getClassName();//获取类的名字
if(name.contains("er")) {
return true;//如果类的名字中带有"er",则符合过滤的要求
}
return false;
}
}
2.在注解类上@ComponentScan.Filter(type=FilterType.CUSTOM,classes = {MyTypeFilter.class})
@ComponentScan(value = "com.zm",includeFilters = {
@ComponentScan.Filter(type=FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false)
1.4 @Scope
可以注解在类和方法,注解在类上默认对类里所有bean生效 。注解在方法中只对当前方法生成的Bean有效
value:指定bean的Scope。有singleton,prototype,request,session值,默认值为singleton。
singleton:单实例,在IOC容器启动后就创建该bean对象。
prototype:多实例,IOC容器启动不会创建该bean对象,在使用该bean时才会创建对象。
scopeName:设置scope的名称
proxyMode:设置生成的代理方式。值为ScopedProxyMode枚举类型中的值。默认值DEFAULT
DEFAULT、NO、INTERFACES(JDK方式)、TARGET_CLASS(CGLIB方式)
@Scope(value="singleton",proxyMode = ScopedProxyMode.DEFAULT)
1.5 @Lazy
注解可以用在类、方法、构造器、属性等。
value属性默认是true,使用@Lazy注解后默认就是延迟加载。
1.6 @Conditional
注解可以作用在类和方法上。作用在类上控制类中的所有bean按照条件判断注册。作用在方法身上控制方法中的bean按照条件进行注解。
value值为Condition[]。当value中有多个Condition时,必须所有的类返回条件为true,才会生成bean。
1、自定义一个类,实现org.springframework.context.annotation.Condition
接口,重新匹配条件。
public class WindowsCondition implements Condition {
/**
* @param conditionContext:判断条件能使用的上下文环境
* @param annotatedTypeMetadata:注解所在位置的注释信息
* */
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//获得当前系统名
String property = environment.getProperty("os.name");
//包含Windows则说明是windows系统,返回true
if (property.contains("Windows")){
return true;
}
return false;
}
}
2、在方法上使用@Conditional(value={自定义Condition类})
@Conditional(value={WindowsCondition.class})
@Bean(value="linus")
public Person person02() {
return new Person("linus", 48);
}
1.7 @Import
注解作用在类上。value为Class[]数组
用法:
1. 直接写上需要注入的Bean的类型
@Import({Cat.class, Dog.class})
2. 通过ImportSelector方式注入Bean
自定义类实现ImportSelector接口,在重写的方法中,将需要注入的bean的全类名放入到String[]中,然后在 @Import中加上自定义的类
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//将Employee类注入
return new String[]{Employee.class.getName()};
}
}
@Import({Cat.class, Dog.class, MyImportSelector.class})
3. 通过ImportBeanDefinitionRegistrar方式注入Bean
自定义类实现ImportBeanDefinitionRegistrar接口,在重写方法中注入bean信息
public class MyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition definition = new RootBeanDefinition(Country.class);
//definition.setScope("singleton");
//void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
//beanName:给Bean对象设置名称
//beanDefinition:设置bean的相关信息。可以设置scope,init-method等等信息
registry.registerBeanDefinition("country",definition);
}
}
@Import({Cat.class, Dog.class, MyImportSelector.class,MyRegistrar.class})
1.8 使用FactoryBean注入Bean
自定义一个类实现FactoryBean接口,重写方法。
//CatFactoryBean 用于创建Cat对象
public class CatFactoryBean implements FactoryBean<Cat> {
@Override
public Cat getObject() throws Exception {
return new Cat();
}
@Override
public Class<?> getObjectType() {
return Cat.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
//注入。实际创建的bean的类型是Cat.class
@Bean
public CatFactoryBean catBean(){
return new CatFactoryBean();
}
1.9 Bean的生命周期
管理bean的生命周期
- @Bean中可以initMethod和destroyMethod值
@Bean(initMethod = "init",destroyMethod = "destroy")
public Teacher teacher(){
return new Teacher();
}
2.通过Bean实现InitializingBean, DisposableBean接口
public class Student implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("销毁destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化init");
}
}
3.使用@PostConstruct和@PreDestroy注解
public class Lion {
public Lion(){}
@PostConstruct
public void initmethod(){
System.out.println("Lion...initmethod");
}
@PreDestroy
public void destroymethod(){
System.out.println("Lion...initmethod");
}
}
1.10 @Controller @Service @Repository @Component
@Controller注解标注在Controller类上,@Service注解标注在Service的实现类上,@Repository注解标注在Dao的实现类上,@Component用于非Controller、Service、DAO类之外的类上,通用类。
在@Import中会自动扫描到标注了这些注解的类,主动注入到IOC 容器中。
1.11 @Value
修饰字段,方法,入参,实现属性注入 值。
1.12 @PropertySource
指定文件地址。提供了一种方便的、声明性的机制,用于向Spring的环境添加PropertySource。与@configuration类一起使用。
1.13 @Autowired @Qualifier @Primary
@Autowired:依赖注入,按照类型从容器中找对应的bean。如果容器中有多个相同类型的组件,再将属性的名称作为组件的id去容器中查找。可以设置required = false。
@Qualifier:和@Autowired组合使用,指定需要装配的组件的id。而不是使用属性名
@Primary :让spring自动装配的时候,默认使用首选的bean。
1.14 @Resource @Inject
@Resource: JSR-250提供的注解 。功能和@Autowired一样。默认按照属性名称查找注入
@Inject : JSR-330提供的注解 。功能和@Autowired一样,需要导入java.inject包。
1.15 @Profile
使用@Profile注解类或者方法,实现在不同情况下选择实例化不同的Bean。@Profile(“dev”)表示为dev时实例化。
@Profile("dev")
2. AOP相关注解
2.1 @EnableAspectJAutoProxy
注解@EnableAspectJAutoProxy表示开启代理。
proxyTargetClass:默认为false,表示使用jdk动态代理织入增强。proxyTargetClass设置为true,表示使用Cglib动态代理技术织入增强。proxyTargetClass设置为false,但是目标类没有声明接口,Spring aop还是会使用Cglib动态代理,也就是说非接口的类要生成代理都用Cglib。
- Jdk代理:基于接口的代理,一定是基于接口,会生成目标对象的接口的子对象。
- Cglib代理:基于类的代理,不需要基于接口,会生成目标对象的子对象。
2.2 @Aspect
注解在类上,表示该类是一个切面类。
2.3 通知
- @Before() :
- @After():
- @AfterReturning() :
- @AfterThrowing():
- @Around():
@Pointcut("execution(* com.zm.service..*(..))")
public void pointcut(){
}
@Before("execution(* com.zm.service..*(..))")
public void before(JoinPoint jp){
System.out.println("ArithmeticAspect..before()..");
}
@After("execution(* com.zm.service..*(..))")
public void after(JoinPoint jp){
System.out.println("参数为:"+Arrays.toString(jp.getArgs()));
System.out.println("ArithmeticAspect..after()..");
}
@AfterReturning("pointcut()")
public void afterReturning(){
System.out.println("ArithmeticAspect..afterReturning()..");
}
@AfterThrowing("pointcut()")
public void afterThrowing(){
System.out.println("ArithmeticAspect..afterThrowing()..");
}
@Around("pointcut()")
public void around(ProceedingJoinPoint pjp){
try{
pjp.proceed();
}catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
}
}
2.4 @Pointcut
通过注解**@Pointcut**定义切点,同一个类中的通知可以直接引用切点的方法名。不是同一个类中的引用需要加上全类名。
3. 事务相关注解
3.1 @EnableTransactionManagement
开启事务管理
3.2 @Transactional
事务,可以注解在类和方法上。注解在类上,表示该类的所有方法都需要事务控制,注解在方法上表示该方法需要事务控制。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
属性名 | 说明 |
---|---|
name | 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。 |
propagation | 事务的传播行为,默认值为 REQUIRED。 |
isolation | 事务的隔离度,默认值采用 DEFAULT。 |
timeout | 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
read-only | 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。 |
rollback-for | 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。 |
no-rollback- for | 抛出 no-rollback-for 指定的异常类型,不回滚事务。 |