<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
">
<!--component:组件,bean-->
<!--scan:扫描-->
<!--开启包扫描,扫描的是base-package路径下的所有类-->
<!--扫描的时候,查看这些类上面有没有写Spring的注解-->
<context:component-scan base-package="com.javasm"/>
<!--读取配置文件-->
<context:property-placeholder location="test.properties"/>
<!--直接 把JDK自己的数据类型,装到Spring容器中,当做bean-->
<!--使用场景:需要给源码中的某些值赋值,或者阅读其他框架的源码-->
<util:list id="heros">
<value>莱因哈特</value>
<value>源氏</value>
<value>半藏</value>
</util:list>
<util:list id="aaaaa">
<value>努巴尼</value>
<value>巴黎</value>
<value>国王大道</value>
</util:list>
<util:map id="items">
<entry key="1001" value="毁灭之刃"/>
<entry key="2001" value="三相之力"/>
<entry key="3001" value="破败王者之刃"/>
</util:map>
<util:set id="abc">
<value>第一滴血</value>
<value>五杀</value>
</util:set>
<util:properties id="config">
<prop key="test1">全屏</prop>
<prop key="test2">测试</prop>
</util:properties>
</beans>
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class Game {
@Value("${game.id}")
private Integer id;
@Value("${name}")
private String name;
@Value("${price}")
private Double price;
//英雄列表
@Value("#{@heros}")
private String[] heros;
//关卡
@Value("#{@aaaaa}")
private List<String> levels;
//背包
@Value("#{@items}")
private Map<Integer,String> items;
//成就
@Value("#{@abc}")
private Set<String> achievements;
//游戏配置
@Value("#{@config}")
private Properties gameConfig;
}
自动注入(必会)
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
- byName(找的是Component之类添加进去的bean名称)
-
- @Resource
- java注解,上面的依赖
//javax.annotation.Resource
//默认情况下,什么参数也不写,也是按照类型寻找bean对象
//@Resource
@Resource(name = "mmm")
//Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'music' available
//加了name属性之后,是根据bean的id寻找bean对象
private Music music;
- byType
-
- @Autowired
org.springframework.beans.factory.annotation.Autowired;
其他注解(了解)
单例
类上面添加注解
@Scope(value = "prototype")//加上后不是单例
@Scope("prototype")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
懒加载
@Lazy
初始化和销毁
@PostConstruct
public void f1(){
System.out.println("初始化");
}
@PreDestroy
public void f2(){
System.out.println("销毁");
}
延伸注解(必会)
作用和Component一致
@Controller 专门用在Controller层
@Service 专门用在Service层
@Repository 专门用在Dao层(后续没有dao的实现类,使用的是MyBatis,所以很少见)
@Component 通用注解(一般实体类不加入Spring容器)
配置类(必会)
@Configuration
public class WebConfig {
//当前类是配置类
//bean对象添加到Spring容器中
//<bean id="teacher" class="com.javasm.demo.Teacher">
@Bean//(添加的Spring容器当中的id为方法名)
public Teacher teacher(){
Teacher t = new Teacher();
t.setId(1001);
t.setName("李雷");
return t;
}
}
@Bean("teacher")//手动设置id
实际应用(必会)
代理模式(了解)
静态代理
在编码阶段,就已经确定,谁是代理类
public interface Programmer {
void code(Integer money);
}
//真实类
public class Xiaoming implements Programmer{
@Override
public void code(Integer money) {
System.out.println("熬夜写代码,获得工资:"+money);
}
}
//代理类
public class DongRuan implements Programmer{
Programmer coder;
public DongRuan(Programmer coder) {
this.coder = coder;
}
@Override
public void code(Integer money) {
System.out.println("收到工资"+money);
System.out.println("发工资7k");
//工作
coder.code(7);
System.out.println("缴纳五险一金 2k");
System.out.println("赚了:"+ (money - 7 - 2));
}
}
public class HuaWei {
public static void main(String[] args) {
Programmer programmer = new DongRuan(new Xiaoming());
programmer.code(30);
}
}
动态代理
编码阶段,不确定代理的类
编码的时候,不知道我要代理的是谁,我要代理,能代理所有的类
代理的规则,在写代理类的时候就已经确定了,不确定的是接口和真实类
JDK
java中,实现JDK动态代理
public class JDKInvocationHandler implements java.lang.reflect.InvocationHandler {
//真实类
private Object target;
public JDKInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method 是正在调用的方法
//invoke执行方法
//统计性能
long start = System.currentTimeMillis();
Object o = method.invoke(target, args);
long time = System.currentTimeMillis() - start;
System.out.println("消耗的毫秒数:"+time);
return o;
}
}
private static void jdkTest1() {
//真实类
PayServiceImpl payServiceImpl = new PayServiceImpl();
//创建代理对象
JDKInvocationHandler jdkInvocationHandler = new JDKInvocationHandler(payServiceImpl);
PayService payService =
(PayService)Proxy.newProxyInstance(
OrderServiceImpl.class.getClassLoader(),
new Class[]{PayService.class},
jdkInvocationHandler
);
payService.del();
}
Cglib
需要额外引入一个依赖,Spring项目默认已经引入了这个依赖
是一个强大的高性能的代码生成库,在代码运行期间,扩展java类和实现Java接口
public class CglibProxyFactory implements org.springframework.cglib.proxy.MethodInterceptor{
//真实类
private Object target;
public Object getInstance(Object target){
this.target = target;
//初始化 真实类
//创建加速器,创建代理类
Enhancer enhancer = new Enhancer();
//设置父类为要代理的类
enhancer.setSuperclass(this.target.getClass());
//设置回调方法
enhancer.setCallback(this);
//创建并返回代理对象
return enhancer.create();
}
@Override
public Object intercept(Object proxy,
Method method,
Object[] args,
MethodProxy methodProxy) throws Throwable {
//method是调用的方法
String name = method.getName();
System.out.println(name+"方法执行之前执行-----"+args);
//执行方法
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("方法执行之后执行------"+result);
return result;
}
}
public static void main(String[] args) {
PayServiceImpl payServiceImpl = new PayServiceImpl();
CglibProxyFactory cglibProxyFactory = new CglibProxyFactory();
PayService payService = (PayService) cglibProxyFactory.getInstance(payServiceImpl);
payService.add();
}
第二天总结
重点
- 必须会背
@Component
@Controller
@Service
@Repository
@Resource
@Autowired
@Configuration
@Bean
- 熟练使用注解三层调用
- 详细描述 @Resource 和 @Autowired区别和共同点
了解
@Scope
@Lazy
@PostConstruct
@PreDestroy
- 代理模式