一.xml配置和注解配置的优缺点
二.两者注解对比
三.代码实例配置演示
1.VideoService:
package net.xdclass.sp.service;
import net.xdclass.sp.domain.Video;
public interface VideoService {
int save(Video video);
Video findById(int id);
}
2.VideoServiceImpl
这里采用了注解@service注入 并取了名字
package net.xdclass.sp.service;
import net.xdclass.sp.dao.VideoDao;
import net.xdclass.sp.domain.Video;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
//@Component("videoService")
@Service("videoService")
public class VideoServiceImpl implements VideoService {
@Autowired
private VideoDao videoDao;
public int save(Video video) {
System.out.println("保存video");
return 1;
}
public Video findById(int id) {
System.out.println("根据id找视频");
videoDao.test();
return new Video();
}
}
3.VideoDao:
package net.xdclass.sp.dao;
import org.springframework.stereotype.Repository;
@Repository("videoDao")
public class VideoDao {
public void test(){
System.out.println("video Dao test ");
}
}
4.APP(启动类)
很关键:AnnotationConfigApplicationContext
package net.xdclass.sp;
import net.xdclass.sp.domain.Video;
import net.xdclass.sp.service.VideoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//扫描指定的包,包括子包
context.scan("net.xdclass");
//里面完成初始化操作,核心方法
context.refresh();
VideoService videoService = (VideoService) context.getBean("videoService");
videoService.findById(2);
// Video video = (Video) context.getBean("video");
// video.init();
}
}
运行结果:
ps:注解导入 并调用init方法实例
video类也有@component
四.代码实例演示2
Video:
此处用了@PostConstruct @PreDestroy注解 起到了bean生命周期的作用
是注解的方式,xml是利用init,destroy函数 见开头文章
scope是作用域,默认是单例,两个相同对象是一个 则相等,prototype是多例,则不相等
package net.xdclass.sp.domain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;
@Component
//@Scope("prototype")
@Scope
public class Video {
private int id;
private String title;
@PostConstruct
public void init(){
System.out.println("video类 init 方法被调用");
}
@PreDestroy
public void destroy(){
System.out.println("video类 destroy 方法被调用");
}
public Video(){
//System.out.println("video 空构造函数被调用");
}
public Video(String title){
//System.out.println("video 带参数构造函数被调用");
this.title = title;
}
public int getId() {
return id;
}
public void setId(int id) {
//System.out.println("Video setId方法被调用");
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
//System.out.println("Video setTitle方法被调用");
this.title = title;
}
}
APP:
package net.xdclass.sp;
import net.xdclass.sp.domain.Video;
import net.xdclass.sp.service.VideoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//扫描指定的包,包括子包
context.scan("net.xdclass");
//里面完成初始化操作,核心方法
context.refresh();
// VideoService videoService = (VideoService) context.getBean("videoService");
//
// videoService.findById(2);
Video video1 = (Video) context.getBean("video");
Video video2 = (Video) context.getBean("video");
System.out.println(video1 == video2);
}
}
运行结果:
这里因为scope默认 所以是单例
五.@Configuration和@Bean注解定义第三方bean
代码:
Appconfig:
有initMethod = “init” 所以会执行初始化init函数
package net.xdclass.sp.config;
import net.xdclass.sp.domain.VideoOrder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class AppConfig {
//使用@bean注解,表明这个bean交个spring 进行管理
// 如果没有指定名称,默认采用 方法名 + 第一个字母小写 作为bean的名称
@Bean(name = "videoOrderName",initMethod = "init",destroyMethod = "destroy")
@Scope
public VideoOrder videoOrder(){
return new VideoOrder();
}
//使用@bean注解,表明这个bean交个spring 进行管理
// 如果没有指定名称,默认采用 方法名 + 第一个字母小写 作为bean的名称
// @Bean(name = "videoOrderName",initMethod = "init",destroyMethod = "destroy")
// @Scope
// public VideoOrder videoOrder(){
// return new VideoOrder();
// }
}
Video:
这里埋一个伏笔,因为他也有@Component 所以也加入了IOC容器里,同时有@PostConstruct注解 会初始化执行函数
package net.xdclass.sp.domain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;
@Component
//@Scope("prototype")
@Scope
public class Video {
private int id;
private String title;
@PostConstruct
public void init(){
System.out.println("video类 init 方法被调用");
}
@PreDestroy
public void destroy(){
System.out.println("video类 destroy 方法被调用");
}
public Video(){
//System.out.println("video 空构造函数被调用");
}
public Video(String title){
//System.out.println("video 带参数构造函数被调用");
this.title = title;
}
public int getId() {
return id;
}
public void setId(int id) {
//System.out.println("Video setId方法被调用");
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
//System.out.println("Video setTitle方法被调用");
this.title = title;
}
}
Videoorder:
package net.xdclass.sp.domain;
import org.springframework.beans.factory.annotation.Autowired;
public class VideoOrder {
private int id;
//订单号
private String outTradeNo;
private Video video;
public VideoOrder(Video video){
this.video = video;
}
public VideoOrder(){
System.out.println("VideoOrder空构造函数被调用");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public Video getVideo() {
return video;
}
public void setVideo(Video video) {
//System.out.println("videoOrder setVideo方法被调用");
this.video = video;
}
public void init(){
System.out.println("VideoOrder init 方法被调用");
}
public void destroy(){
System.out.println("VideoOrder destroy 方法被调用");
}
}
App:
package net.xdclass.sp;
import net.xdclass.sp.domain.Video;
import net.xdclass.sp.domain.VideoOrder;
import net.xdclass.sp.service.VideoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//扫描指定的包,包括子包
context.scan("net.xdclass");
//里面完成初始化操作,核心方法
context.refresh();
VideoOrder videoOrder = (VideoOrder) context.getBean("videoOrderName");
}
}
运行结果:
之所以没有销毁函数执行 是因为缺少注册某样东西
六. Spring的自动映射配置文件PropertySource注解讲解
代码:
config.properties:
server.host=127.0.0.1
server.port=999
CustomConfig:
package net.xdclass.sp.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(value = {"classpath:config.properties"})
public class CustomConfig {
@Value("${server.host}")
private String host;
@Value("${server.port}")
private int port;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
运行结果:
七.AOP案例 注解配置
AnnotationAppConfig
package net.xdclass.sp.aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("net.xdclass")
@EnableAspectJAutoProxy //开启了spring对aspect的支持
public class AnnotationAppConfig {
}
LogAdvice:
package net.xdclass.sp.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
//告诉spring,这个一个切面类,里面可以定义切入点和通知
@Aspect
public class LogAdvice {
//切入点表达式,也可以直接在通知上编写切入点表达式
@Pointcut("execution(* net.xdclass.sp.service.VideoServiceImpl.*(..))")
public void aspect(){
}
//前置通知
//@Before("aspect()")
@Before("execution(* net.xdclass.sp.service.VideoServiceImpl.*(..))")
public void beforeLog(JoinPoint joinPoint){
System.out.println("LogAdvice beforeLog");
}
//后置通知
@After("aspect()")
public void afterLog(JoinPoint joinPoint){
System.out.println("LogAdvice afterLog");
}
/**
* 环绕通知
* @param joinPoint
*/
@Around("aspect()")
public void around(JoinPoint joinPoint){
Object target = joinPoint.getTarget().getClass().getName();
System.out.println("调用者="+target);
//目标方法签名
System.out.println("调用方法="+joinPoint.getSignature());
//通过joinPoint获取参数
Object [] args = joinPoint.getArgs();
System.out.println("参数="+args[0]);
long start = System.currentTimeMillis();
System.out.println("环绕通知 环绕前=========");
//执行连接点的方法
try {
((ProceedingJoinPoint)joinPoint).proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("环绕通知 环绕后=========");
System.out.println("调用方法总耗时 time = " + (end - start) +" ms");
}
}
APP:
package net.xdclass.sp;
import net.xdclass.sp.aop.AnnotationAppConfig;
import net.xdclass.sp.domain.Video;
import net.xdclass.sp.domain.VideoOrder;
import net.xdclass.sp.service.VideoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationAppConfig.class);
VideoService videoService = (VideoService) context.getBean("videoService");
videoService.findById(2);
}
}
这里加了一个睡眠2s,测试环绕计时
运行结果: