| 注解名称 | 说明 |
|---|---|
| @Configuration | 把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。 |
| @ComponentScan | 在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 context:component-scan |
| @Scope | 用于指定scope作用域的(用在类上) |
| @Lazy | 表示延迟初始化 |
| @Conditional | Spring4开始提供,它的作用是按照一定的条件进行判断,满足条件给容器注册Bean。 |
| @Profile | 本质上就是一个条件注解的实现,它可以通过不同环境返回不同的实例对象,常用于数据源切换等。 |
| @import | 导入外部资源 |
| 生命周期控制 | @PostConstruct用于指定初始化方法(用在方法上) @PreDestory用于指定销毁方法(用在方法上) @DependsOn:定义Bean初始化及销毁时的顺序 |
把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。
@Configuration
public class JavaConfig {
}
1.2 @ComponentScan
package com.gupaoedu;
import com.gupaoedu.controller.UserController;
import com.gupaoedu.dao.IUserDao;
import com.gupaoedu.dao.impl.UserDaoImpl;
import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
@Configuration
@ComponentScans({
@ComponentScan(value = {"com.gupaoedu.controller"}
,useDefaultFilters = false
,includeFilters = {@ComponentScan.Filter(Controller.class)})
,@ComponentScan(value = {"com.gupaoedu.service","com.gupaoedu.dao"}
,useDefaultFilters = true
,excludeFilters = {@ComponentScan.Filter(Controller.class)})
})
public class JavaConfig {
}
1.3 @Scope
| 作用域 | 说明 |
|---|---|
| prototype | 每次请求,都是一个新的Bean( java原型模式) |
| singleton | bean是单例的(Java单例模式) |
| request | 在一次请求中,bean的声明周期和request同步 |
| session | bean的生命周期和session同步 |
默认的情况是 singleton
1.4 @LazySpring中Bean的作用域默认是单例的,单例对象默认在IoC容器创建之后就进行创建并放入到IoC容器中。使用@Lazy注解则可以让单例对象在真正用到时才进行创建。
1.5 @Conditional@Conditional注解 通过重写matches方法来动态实现是否加载某类型
package com.gupaoedu.conditional;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypemetadata;
public class ConditionalOnBean implements Condition {
public boolean matches(ConditionContext conditionContext, AnnotatedTypemetadata annotatedTypemetadata) {
return true;
}
}
package com.gupaoedu;
import com.gupaoedu.conditional.ConditionalOnBean;
import com.gupaoedu.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JavaConfig {
@Bean
@Conditional(ConditionalOnBean.class)
public User user(){
return new User();
}
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanName:beanDefinitionNames){
System.out.println(beanName);
}
}
}
Spring中已实现的Conditional注解的类
| @Conditional扩展注解 | 作用(判断是否满足当前指定条件) |
|---|---|
| @ConditionalOnJava | 系统的Java版本是否符合要全 |
| @ConditionalOnBean | 容器中存在指定的Bean |
| @ConditionalOnMissingBean | 容器中不存在指定的Bean |
| @ConditionalOnexpression | 满足SpEL表达式 |
| @ConditionalOnClass | 系统中有指定的类 |
| @ConditionalOnMissingClass | 系统中没有指定的类 |
| @ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
| @ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
| @ConditionalOnResource | 类路径下是否存在指定的资源文件 |
| @ConditionalOnWebApplication | 当前是Web环境 |
| @ConditionalOnNotWebApplication | 当前不是Web环境 |
| @ConditionalOnJndi | JNDI存在指定项 |
根据不同的环境返回不同的对象
package com.gupaoedu.pojo;
@Data
public class GpDataSource {
private String username;
private String password;
private String url;
public GpDataSource(String username, String password, String url) {
this.username = username;
this.password = password;
this.url = url;
}
@Override
public String toString() {
return "GpDataSource{" +
"username='" + username + ''' +
", password='" + password + ''' +
", url='" + url + ''' +
'}';
}
public GpDataSource() {
}
}
package com.gupaoedu;
import com.gupaoedu.conditional.ConditionalOnBean;
import com.gupaoedu.conditional.ConditionalOnClass;
import com.gupaoedu.pojo.GpDataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
@Configuration
public class JavaConfig {
@Bean
@Profile("pro") // 其实Profile注解本质上就是Conditional的一种实现
public GpDataSource proDataSource(){
GpDataSource ds = new GpDataSource("root","123","192.168.11.190");
return ds;
}
@Bean
@Profile("dev")
public GpDataSource devDataSource(){
GpDataSource ds = new GpDataSource("admin","456","192.168.12.190");
return ds;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
// 通过设置不同环境返回不同对象
ac.getEnvironment().setActiveProfiles("dev");
ac.register(JavaConfig.class);
ac.refresh();
System.out.println(ac.getBean(GpDataSource.class));
}
}
1.7 @import
将某个类导入到IoC容器中
1.7.1 静态导入 1.7.2 动态导入 - importSelectorpublic class GpimportSelector implements importSelector {
public String[] selectimports(Annotationmetadata annotationmetadata) {
// 在此处实现不同的业务逻辑控制
return new String[]{LoggerService.class.getName(),CacheService.class.getName()};
}
}
1.7.3 动态导入 - importBeanDefinitionRegistrar
package com.gupaoedu.demo;
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;
public class GpimportBeanDefinitionRegistrar implements importBeanDefinitionRegistrar {
public void registerBeanDefinitions(Annotationmetadata annotationmetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
// 需要将添加的对象包装为一个RootBeanDefinition对象
RootBeanDefinition cache = new RootBeanDefinition(CacheService.class);
beanDefinitionRegistry.registerBeanDefinition("cache",cache);
RootBeanDefinition logger = new RootBeanDefinition(LoggerService.class);
beanDefinitionRegistry.registerBeanDefinition("logger",logger);
}
}
1.8 @PostConstruct @PreDestory @DependsOn
@PostConstruct 用于指定初始化方法(用在方法上)
@PreDestory 用于指定销毁方法(用在方法上)
@DependsOn 指定实例化对象的先后顺序
@Component
// Person的实例化依赖于User对象的实例化,也就是User先于Person实例化
@DependsOn({"user"})
public class Person {
public Person(){
System.out.println("Person 构造方法执行了...");
}
}
2.赋值注解
| 注解名称 | 说明 |
|---|---|
| @Component | 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 |
| @Service | 用于标注业务层组件 |
| @Controller | 用于标注控制层组件 |
| @Repository | 用于标注数据访问组件,即DAO组件。 |
| @Value | 普通数据类型赋值 |
| @Autowired | 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用 |
| @PropertySource | 读取配置文件赋值 |
| @Qualifier | 如存在多个实例配合使用 |
| @Primary | 自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常 |
| @Resource | 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。 |
@Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注;
@Controller:用于标注控制层组件;
@Service:用于标注业务层组件;
@Repository:用于标注数据访问组件,即DAO组件。
package com.gupaoedu.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
@Component
@Data
public class User {
@Value("bobo") // 注入普通的字符串
private String userName ;
@Value("#{systemProperties['os.name']}")
private String systemPropertiesName; // 注入操作系统的信息
@Value("#{T(java.lang.Math).random()*100}")
private double randomNumber; // 注入表达式的结果
@Value("#{person.personName}")
private String fromPersonName; // 注入其他Bean的属性
@Value("classpath:test.txt")
private Resource resourceFile;
@Value("http://www.baidu.com")
private Resource baiduFile;
}
2.3 @Autowired
默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用
2.4 @Qualifier如存在多个实例配合使用
2.5 @PropertySource在Java配置类中通过@PropertySouce注解来显示的引入属性文件
@Configuration
@ComponentScan("com.gupaoedu")
// 显示的指定要加载的属性文件
@PropertySource({"classpath:spring-db.properties"})
public class JavaConfig {
}
2.6 @Primary
自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
2.7 @Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
3. 织入注解| 注解名称 | 说明 |
|---|---|
| @ApplicationContextAware | 可以通过这个上下文环境对象得到Spring容器中的Bean |
| @BeanDefinitionRegistryPostProcessor | BeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor接口,是Spring框架的BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefiniton |
| 注解名称 | 说明 |
|---|---|
| @EnableTransactionManagement | 添加对事物管理的支持 |
| @Transactional | 配置声明式事物 |
| @EnableAspectJAutoProxy | 启用对AspectJ的支持 |
| @Aspect | 声明为切面类 |
| 通知类型 | @Before:前置通知,目标方法执行之前调用。 @AfterReturning:后置通知,目标方法执行完成之后调用。 @Around:环绕通知,目标方法执行前后都会调用方法,且能增强结果。 @AfterThrowing:异常通知,目标方法出现异常调用。 @After:最终通知,无论程序执行是否正常,该通知都会执行。类似于try…catch中finally代码块。 |
@Configuration
@EnableAspectJAutoProxy // 放开AspectJ的使用
@ComponentScan
public class JavaConfig {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
IUserService bean = ac.getBean(IUserService.class);
bean.fun1();
}
}
4.4 @Aspect
package com.gupaoedu.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect // 显示的表明当前类是一个切面类
@Component // 将该对象加载到IoC容器中
public class MyAspectJ01 {
@Before("execution(* com.gupaoedu.service.impl.*.fun2(..))")
public void aspectMethod01(){
System.out.println("before ....");
}
}
4.5 通知类型
package com.gupaoedu.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAspectJ02 {
@Before("execution(* com.gupaoedu.service.impl.*.*(..))")
public void before(){
System.out.println("before ...");
}
@AfterReturning(value = "within(com.gupaoedu.service.impl.*)",returning = "res")
public void afterReturning(Object res){
System.out.println("后置通知..." + res);
}
@Around(value = "within(com.gupaoedu.service.impl.*)")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("目标对象before....");
Object[] args = proceedingJoinPoint.getArgs();
Object res = proceedingJoinPoint.proceed(); // 目标对象方法执行
System.out.println("目标对象after...." + res);
return res;
}
@AfterThrowing(value = "within(com.gupaoedu.service.impl.*)",throwing = "ex")
public void afterThrowing(Exception ex){
System.out.println("异常通知产生了..." + ex);
}
@After(value = "within(com.gupaoedu.service.impl.*)")
public void after(){
System.out.println("最终通知...");
}
}
4.5.1 切入点表达式
| 表达式类型 | 说明 |
|---|---|
| execution | 定位到目标对象的方法上 |
| within | 定位到具体的类型上 |
| this | 代理对象的类型 |
| target | 目标对象的类型 |
| args | 参数的类型 |
| @args | 传入的参数有被该注解修饰 |
| @within | 类型修饰的注解 |
| @annotation | 方法修饰的注解 |
execution表达式
语法: execution([访问权限类型] 返回值类型 [全限定类名] 方法名(参数名) [抛出的异常类型])
| 符合 | 含有 |
|---|---|
| * | 0到多个符合 |
| … | 方法参数中表示任意个参数,用在报名后表示当前包及其子包 |
| + | 用在类名后表示当前类及其子类,用在接口后表接口及其实现 |
示例:
execution(public * *(. .)) 指定切入点为:任意公共方法。 execution(* set *(. .)) 指定切入点为:任何一个以“set”开始的方法。 execution(* com.xyz.service.*.*(. .)) 指定切入点为:定义在service包里的任意类的任意方法。 execution(* com.xyz.service. .*.*(. .)) 指定切入点为:定义在service包或者子包里的任意类的任意方法。“..”出现在类名中时, 后面必须跟“*”,表示包、子包下的所有类。 execution(* *.service.*.*(. .)) 指定只有一级包下的serivce子包下所有类(接口)中的所有方法为切入点 execution(* *. .service.*.*(. .)) 指定所有包下的serivce子包下所有类(接口)中的所有方法为切入点



