@SpringBootApplication,springboot项目启动入口注解,是由@SpringBootConfiguration、 @EnableAutoConfiguration、 @ComponentScan三个注解组合而成。
@SpringBootConfiguration是springboot对于spring注解@Configuration的派生注解,标注这个类是一个配置类
@EnableAutoConfiguration注解,开启自动装配。是由@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)组合而成。
@ComponentScan自动扫描组件包,只要标注了@Controller、@Service、@Repository、@Component这四个注解都会被扫描到容器中。
@Service:服务层组件,用于标注业务层组件,表示定义一个bean,自动根据bean的类名实例化一个首写字母为小写的bean,例如Chinese实例化为chinese,如果需要自己改名字则:@Service("你自己改的bean名")。
@Controller:用于标注控制层组件(如struts中的action) 。
@Repository:持久层组件,用于标注数据访问组件,即DAO组件。
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
SpringBoot在写启动类的时候如果不使用@ComponentScan指明对象扫描范围,默认指扫描当前启动类所在的包里的对象,如果你的其他包都在使用了@SpringBootApplication注解的主类所在的包及其下级包,则你什么都不用做,SpringBoot会自动帮你把其他包都扫描了。为了方便,我们一般都把主类放在了所有类的上一级包中,如项目所有的class文件都放在了包com.beauty的下级包中,则把spring boot的主类放在包com.beauty下。
如果当前启动类没有包,则在启动时会报错:Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package错误,因为启动类不能直接放在main/java文件夹下,必须要建一个包把它放进去或者使用@ComponentScan指明要扫描的包。
如果你有一些bean所在的包,不在主类的包及其下级包,那么你需要手动加上@ComponentScan注解并指定那个bean所在的包。
注:@ComponentScan的不同写法
1.@ComponentScan({“com.xiao.hui”,“com.xiao.qiang”})或@ComponentScan(basePackages = {“com.xiao.hui”,“com.xiao.qiang”})
2.@ComponentScan(“com.xiao”)或@ComponentScan(value = “com.xiao”)或@ComponentScan(basePackages = { “com.xiao” })
3.@ComponentScan(basePackageClasses=要扫描类.class所在位置的包) 意思是要扫描哪个类所在的包,如@ComponentScan(basePackageClasses=hehe.class),这种写法不如上面的那种写法好有局限性
在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。
在接口前面标上@Autowired和@Qualifier注释使得接口可以被容器注入,当接口存在两个实现类的时候必须指定其中一个来注入,使用实现类首字母小写的字符串来注入,如:
@Autowired
@Qualifier("chinese")
private Man man;
否则可以省略,只写@Autowired 。
Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配顺序
1、 @Autowired与@Resource都可以用来装配bean.都可以写在字段上,或写在setter方法上。
2、 @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false),如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:
@Autowired() @Qualifier("baseDao")
private BaseDao baseDao;
3、@Resource(这个注解属于J2EE的),默认安装名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
@Resource(name="baseDao")
private BaseDao baseDao;
推荐使用:@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅。
切面(Advisor):表示从业务逻辑中分离出来的横切逻辑,比如性能监控,日志记录,权限控制等
连接点(JointPoint):程序执行过程中明确的点,一般是方法的调用
通知(Advice): 通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间
切入点(PointCut): 就是带有通知的连接点,切入点指切面具体织入的方法
织入(Weaving): 织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入
目标对象(Target): 目标对象指将要被增强的对象。即包含主业务逻辑的类的对象
spring对AOP有两种实现方式,一种是动态代理,它是通过接口方式实现的,要求所代理的类一定是实现了某一个接口,对一般的类就无法代理,spring默认是这种;一种是通过设置proxy-target-class="true",则是使用CGLIB实现AOP,CGLIB直接生成二进制码,使得普通类也可以实现AOP。
1.添加aop依赖:
org.springframework.boot
spring-boot-starter-aop
2.配置参数:
spring.aop.proxy-target-class="true"
当同时有个多切面需要执行时,通过Order来定义优先级,值越小越优先执行。例如有两个切面,一个是记录请求@Order(1),一个是验证接口中的参数@Order(2),那么切面方法的执行顺序是先执行@Order(1)的before, 再执行@Order(2)的before; 然后再执行@Order(2)的@After或@AfterReturning,最后再执行@Order(1)的@After或@AfterReturning