@Target
目标,对象。
@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})分别表示该注解可以出现在类上,属性上,方法上。
标注注解的注解叫做元注解,@Target(ElementType.TYPE)用来修饰@Component可以出现的位置。
@Target({ElementType.TYPE,ElementType.FIELD})表示@Component注解可以出现在类上,属性上。
@Target(ElementType.TYPE)表示@Component注解只能出现在类上。
使用某个注解时,如果注解的属性名是value的话,value可以省略。@Target({ElementType.TYPE})
使用某个注解时,如果注解的属性是数组,并且数组中只有一个元素,大括号可以省略。
@Target(ElementType.TYPE)
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Component {
String value();
}
以上是自定义了一个注解:Component
该注解上面修饰的注解包括:Target注解和Retention注解,这两个注解被称为元注解。
Target注解用来设置Component注解可以出现的位置,以上代表表示Component注解只能用在类和接口上。
Retention注解用来设置Component注解的保持性策略,以上代表Component注解可以被反射机制读取。
String value(); 是Component注解中的一个属性。该属性类型String,属性名是value。
@Retention
保留,保持
@Retention(RetentionPolicy.RUNTIME)也是个注解(设置注解的保持性策略),用来标注
该注解最终保留在class文件当中,并且可以被反反射机制读取。
@Target(value={ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Controller 、@Service、@Repository、@Component
controller控制器 Service服务 Repository仓库 Component组件这四个注解常用来负责声明Bean。
@Controller、@Service、@Repository这三个注解都是@Component注解的别名。为了增强数据的可读性一般,控制器类上使用:Controller,service类上使用:Service,dao类上使用:Repository
他们都是只有一个value属性。value属性用来指定bean的id,也就是bean的名字。
@Value、@Autowired、@Qualifier、@Resource
Value值,数值;Autowired自动装配;Qualifier修饰词;Resource资源
当属性的类型是简单类型时,可以使用@Value注解进行注入。目的是给简单类型的属性赋值。
@Value注解可以出现在属性上、setter方法上、以及构造方法的形参前。
@Value(value = "zhangsan")
private String name;//属性上
@Value("李四")
public void setName(String name) {
this.name = name;//set方法上
}
public User(@Value("隔壁老王") String name, @Value("33") int age) {//构造方法参数前
this.name = name;
this.age = age;
}
@Autowired注解可以用来注入非简单类型。目的是给非简单类型赋值。
单独使用@Autowired注解,默认根据类型装配。
注解可以标注在属性上,set方法上,构造方法上,构造方法的形参前。
当有参数的构造方法只有一个时,@Autowired注解可以省略。如果有多个构造方法,@Autowired肯定是不能省略的。
@Autowired注解默认是byType进行注入的,也就是说根据类型注入的。如果一个接口有多个实现类则会报错。此时需要通过名字注入。
public interface UserDao {
void insert();
}
@Autowired // 在属性上注入
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserService(@Autowired UserDao userDao) {
this.userDao = userDao;
}
@Autowired注解和@Qualifier注解联合起来才可以根据名称进行装配,在@Qualifier注解中指定Bean名称。
@Autowired
@Qualifier("userDaoForOracle") // 这个是bean的名字UserDao的其中一个具体实现类。
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Resource注解也可以完成非简单类型注入。那它和@Autowired注解有什么区别?
@Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。而@Autowired注解是Spring框架自己的。
@Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。
@Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。
@Resource注解用在属性上、setter方法上。
@Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。
当@Resource注解使用时没有指定name的时候,还是根据name进行查找,这个name是属性名。
@Resource注解:默认byName注入,没有指定name时把属性名当做name,根据name找不到时,才会byType注入。byType注入时,某种类型的Bean只能有一个
@Configuration、@ComponentScan
Configuration配置;ComponentScan组件扫描
@Configuration注解的作用:声明一个类为配置类,用于取代bean.xml配置文件注册bean对象。
@ComponentScan用于批量注册bean。
这个注解会让spring去扫描某些包及其子包中所有的类,然后将满足一定条件的类作为bean注册到spring容器容器中。
@Configuration
@ComponentScan({"com.powernode.dao","com.powernode.service"})
public class Spring6Config {
}
@Aspect
切面类 @Aspect: 定义切面类,加上@Aspect、@Component注解
@Component("logAspect")
@Aspect//切面类是需要使用@Aspect注解标注的
public class LogAspect {//切面
//切面 = 通知 + 切点
//通知就是增强,就是具体要编写的增强代码
//通知Advice以方法形式出现
//@Before(切点表达式)注解标注的方法就是一个前置通知
//@Before("execution(修饰符 返回值类型 全限定类名 方法名(形式参数列表) 异常)")
@Before("execution(* com.powernode.spring6.service.UserService.log*(..))")
public void beforeAdvice(){
System.out.println("我是一个通知,我是一段增强代码。。。");
}
}
Advice 通知类型相关注解
● 前置通知:@Before 目标方法执行之前的通知
@Before("execution(* com.powernode.spring6.service..log*(..))")
public void beforeAdvice(){
System.out.println("前置通知");
}
● 后置通知:@AfterReturning 目标方法执行之后的通知
@AfterReturning("execution(* com.powernode.spring6.service..log*(..))")
public void afterReturningAdvice(){
System.out.println("后置通知");
}
● 环绕通知:@Around 目标方法之前添加通知,同时目标方法执行之后添加通知。
//环绕通知是最大的通知,在前置通知之前,在后置通知之后
@Around("execution(* com.powernode.spring6.service..log*(..))")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//前环绕代码
System.out.println("前环绕");
//执行目标,需要连接点。
proceedingJoinPoint.proceed();
//后环绕代码
System.out.println("后环绕");
}
● 异常通知:@AfterThrowing 发生异常之后执行的通知
● 最终通知:@After 放在finally语句块中的通知
//最终通知
@After("execution(* com.powernode.spring6.service..log*(..))")
public void afterAdvice(){
System.out.println("最终通知");
}
执行顺序(没有异常的情况下):
前环绕
前置通知
系统正在认证身份
后置通知
最终通知
后环绕
@Order
业务流程当中不一定只有一个切面,可能有的切面控制事务,有的记录日志,有的进行安全控制,如果多个切面的话,顺序如何控制:可以使用@Order注解来标识切面类,为@Order注解的value指定一个整数型的数字,数字越小,优先级越高。
@Component("logAspect")
@Aspect//切面类是需要使用@Aspect注解标注的
@Order(1)//设置优先级
public class LogAspect {//切面
@Before("execution(* com.powernode.spring6.service..log*(..))")
public void beforeAdvice(){
System.out.println("前置通知");
}
}
@Pointcut
用来定义通用的切点表达式。
@Pointcut("execution(* com.powernode.spring6.service..log*(..))")
public void universalPoint(){
//这个方法只是个标记,方法名随意,方法体中也不需要写任何代码。
}
//@Before(切点表达式)注解标注的方法就是一个前置通知
//@Before("execution(修饰符 返回值类型 全限定类名 方法名(形式参数列表) 异常)")
@Before("universalPoint()")
public void beforeAdvice(){
System.out.println("前置通知");
}
@EnableAspectJAutoProxy
@Configuration //替代spring.xml文件
@ComponentScan("com.powernode.spring6.service") // 组件扫描
@EnableAspectJAutoProxy(proxyTargetClass = true) // 启用aspectj自动代理机制
public class Spring6Config {
}
@Transactional
该注解可以应用于类级别和方法级别,并提供了各种选项来自定义事务管理。事务是指一系列的操作,在一个事务中,要么所有操作都成功完成,要么所有操作都回滚。在数据库中,这些操作通常是对一组相关的数据进行的增删改查操作。事务性的主要目的是确保数据的一致性和完整性,因为当一组操作中的任何一个操作失败时,整个事务将回滚到最初的状态。
@Transactional注解可以接受一些属性来自定义事务的行为。以下是一些常用的属性:
propagation:定义事务的传播行为。默认值是REQUIRED,表示当前方法必须在一个事务中运行,如果没有现有事务,则创建一个新事务。其他可能的选项包括SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED和NEVER。
isolation:定义事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。其他可能的选项包括READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE。
readOnly:定义事务是否只读。如果设置为true,则该事务只能读取数据,不能修改数据。这可以用来优化性能,并减少锁定冲突的可能性。
timeout:定义事务的超时时间,以秒为单位。如果事务在超时时间内没有完成,则会自动回滚。
rollbackFor:定义哪些异常会触发事务回滚。默认情况下,只有未检查异常会导致回滚。使用rollbackFor属性可以指定其他异常类。
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, timeout = 30, rollbackFor = Exception.class)
public void transfer(String fromActno, String toActno, double money) {
Account fromAccount = accountDao.selectByActno(fromActno);
Account toAccount = accountDao.selectByActno(toActno);
fromAccount.setBalance(fromAccount.getBalance() - money);
toAccount.setBalance(toAccount.getBalance() + money);
accountDao.update(fromAccount);
//int i = 1 / 0; //抛出异常,测试事务回滚
accountDao.update(toAccount);
}
}
@Bean
spring框架看到Bean注解后会调用这个被标注的方法,这个方法的返回值是一个Java对象,这个Java对象会自动纳入ioc容器管理。
//spring框架看到Bean注解后会调用这个被标注的方法,这个方法的返回值是一个Java对象,这个Java对象会自动纳入ioc容器管理。
//放回的对想就是spring容器中的一个Bean了
//这个返回的Bean的id(name)是dataSource
@Bean(name = "dataSource")
public DruidDataSource getDruidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/spring6");
druidDataSource.setUsername("root");
druidDataSource.setPassword("1234");
return druidDataSource;
}
@RunWith、@ContextConfiguration
@RunWith和@ContextConfiguration是JUnit测试中常用的注解,用于指定测试的运行环境。
@RunWith注解用于指定测试运行器,Spring框架提供了一个专门的测试运行器org.springframework.test.context.junit4.SpringJUnit4ClassRunner。这个运行器可以自动加载Spring配置文件,并注入相应的Bean,使测试环境和实际运行环境尽量一致。
@ContextConfiguration注解用于指定Spring配置文件的位置,可以指定XML配置文件或者是Java配置类。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
public class SpringJUnit4Test {
@Autowired
private User user;
@Test
public void testUser(){
System.out.println(user.getName());
}
}
@RunWith注解指定了测试运行器为SpringJUnit4ClassRunner,@ContextConfiguration注解指定了Spring配置文件的位置为classpath:applicationContext.xml。在测试方法中,通过@Autowired注解注入了UserService的实现类。测试运行时,SpringJUnit4ClassRunner运行器会加载applicationContext.xml配置文件,并注入UserService的实现类,以便UserServiceTest类可以进行测试。
@ExtendWith
@ExtendWith(SpringExtension.class)是JUnit 5中用于扩展测试的注解,它提供了Spring测试上下文框架的集成。当测试类使用@ExtendWith(SpringExtension.class)时,Spring会自动加载测试配置,创建应用程序上下文并将其注入测试类中。这允许测试类使用Spring注入的bean和其他Spring功能。
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:spring.xml")
public class SpringJUnit5Test {
@Autowired
private User user;
@Test
public void testUser(){
System.out.println(user.getName());
}
}