Spring学习笔记
在配置好需要的文件后就可以进行编程学习了。。
Spring基于XML文件配置Bean的方法:
在IOC容器中配置:
<beans ... ...>
<bean id="helloWorld" class="com.spring.beans.HelloWorld">
<property name="name" value="spring"></property> //属性注入
<property name="sex" value="man"></property>
<constructor-arg value="spring" ></constructor-arg> //构造器注入
<constructor-arg value="sex"></constructor-arg>
<constructor-arg value="spring" index="0"></constructor-arg> //和上例效果相同
<constructor-arg value="sex" index="1">
<constructor-arg value="spring" type="String"></constructor-arg>
<constructor-arg value="sex" type="String"></constructor-arg>
</bean>
</beans>
1.创建spring的IOC容器
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
2.从IOC容器中获取Bean的实例
HelloWorld helloWorld=(HelloWorld)ctx.getBean(HelloWorld.class); //只能有一个HelloWorld类型的Bean
HelloWorld helloWorld=ctx.getBean("helloWorld");
属性配置细节
1.当要给变量赋值特殊符号时可用<![CDATA["赋值内容"]]>包裹起来。
2.属性值也可以用 value 直接点进行配置
3.可以使用property的 ref 属性建立 bean之间的引用关系。
4.内部 Bean 不能被外部影响,只能内部使用。
5.可以使用 <null/> 标签为某些属性注入 null 值
6.使用级联属性赋值时,必须先初始化后才可以为级联属性赋值,当前 Bean 内必须有 get和set -ref对象的方法。
7.使用<list>标签时,若引用的 Bean 是另一个包里的同名类,则应 import 另一个包的该同名类。
8.使用 util 标签来配置单例的集合bean,以供多个bean进行引用,需要导入util命名空间。
9.使用 P命名空间为 bean 的属性赋值,需要导入p命名空间。相对于传统的方式更加简洁。
格式 : <bean id="person" class="com.spring.beans.Person" p:name="name" p:age="15" ></bean>
10.可以使用 autowire 自动装配,有byName,byType,constructor等方式。
<bean id="person" class="com.spring.beans.autowire.Person"
autowire="byName">
</bean>
11.bean之间的关系:bean 可以继承 (parent)、依赖(depends-on),bean的abstract属性为true,这样的bean不能被IOC容器实例化,只用来被继承配置
不会继承 bean 的所有属性,例如:autowire、abstract……若某一个bean的 class 属性没有指定,则该 bean 必须是一个抽象 bean。
depends-on 属性会将 前置依赖的Bean在本Bean实例化之前创建好。如果依赖于多个Bean,则可以通过 逗号、空格 配置Bean的名称。
12.Bean的作用域 : 可以用 scope 属性配置。 singleton 是默认值,容器初始时创建实例,在整个容器生命周期内至创建这一个 bean。 prototype 是原型的,容器初始化时不创建 bean 的实例,而是在每次请求时创建新的 bean实例并返回。
13.可以使用外部属性文件配置Bean。<context:property-placeholder location="classpath: db.source" /> <property name="user" value="${user}">.
14.SpEL : 可以使用 SpEL 来给 Bean 配置 。
(1) 当要给 字符串类型赋值时 : value="#{'abc'}"
(2) 当赋 整型、浮点型时 : value="#{14}" value="#{123.321}"
(3) 当引用其他 属性时 : value="#{car}" value="#{car.price}"
(4) 当引用类的静态属性时: value="#{T(java.lang.Math).PI*8}"
(5) 当使用运算符时: value="#{ 10>5? '大于' : '小于' }"
-
可以自行设置 Bean 的 init()方法 和 destroy() 方法。 先在 Bean Class 里将init()和destroy()方法写好,名字自订,然后在xml文件里配置。
例:<bean id="person" class="com.spring.beans.Person" init-method="init3" destroy-method="destroy"></bean>
16.可以添加 Bean后置处理器。通过写一个 BeanPostProcessor 接口类,然后在里面重写 postProcessAfterInitialization(init后执行)和postProcessBeforeInitialization(init前执行) 方法,并在xml文件里配置。
例:
<bean class="com.spring.beans.MyBeanPostProcessor"></bean>
17.可以使用静态工厂方法配置bean:先创建一个静态工厂方法类,例:
public class StaticGameFactory {
private static Map<String,Game> games=new HashMap<String,Game>();
static{
games.put("ChiJi", new Game("ChiJi",98));
games.put("H1Z1", new Game("H1Z1",68.0));
}
//静态工厂方法
public static Game getGame(String name){
return games.get(name);
然后在xml文件里通过静态工厂方法来配置bean。
例:
<bean id="game" class="com.spring.beans.factory.Game" factory-method="getGame">
<constructor-arg value="cf"></constructor-arg></bean> //如果工厂方法需要传入参数,则使用constructor-arg来配置参数
18.也可以使用实例工厂方法配置bean:
public class InstanceGameFactory {
private Map<String,Game> games;
public InstanceGameFactory(){
games=new HashMap<String,Game>();
games.put("CF", new Game("CF",0));
games.put("dnf", new Game("dnf",1));
}
public Game getGame(String name){
return games.get(name);
}
需要先配置工厂的实例:
<bean id="gameFactory" class="com.spring.beans.factory.InstanceGameFactory"></bean>
然后再配置 bean 实例: //factory-bean 指向实例工厂方法的bean factory-method指向实例工厂方法的名字; 如果工厂方法需要传入参数,则使用constructor-arg来配置参数
<bean id="game2" factory-bean="gameFactory" factory-method="getGame"><constructor-arg value="CF"></constructor-arg></bean>
19.通过FactoryBean 来配置 bean。 首先自定义FactoryBean,需要实现FactoryBean 接口,然后在xml文件里 通过 FactoryBean 来配置Bean的实例,例:
class:指向FactoryBean的全类名;property:配置FactoryBean的属性; 实际返回的是 FactoryBean 的 getObejct() 方法的实例
<bean id="game" class="com.spring.beans.factorybeans.GameFactoryBean">
<property name="name" value="qwe"></property>
</bean>
20.通过注解配置Bean
<!-- 指定Spring IOC 容器扫描的包 -->
<!-- context:component-scan 子节点base-package="" 指定扫描该包及其子包 -->
<!-- 可通过 resource-pattern 指定扫描的资源 -->
<!--
<context:component-scan base-package="com.spring.beans.annotation"
resource-pattern="repository/*.class"
></context:component-scan>
-->
<!-- context:exclude-filter 子节点指定不包含哪些表达式的组件 -->
<!-- context:include-filter 子节点指定包含那些表达式的组件,该节点需要use-default-filters 配合使用(use-default-filters="false")-->
<context:component-scan base-package="com.spring.beans.annotation"
use-default-filters="true"><!-- type="annotation" 是扫描base-package 包及其所有子包-->
<!--
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />
-->
<!-- type="assignable" 是扫描指定类及implements它的类 -->
<context:exclude-filter type="assignable" expression="com.spring.beans.annotation.repository.UserRepository" />
</context:component-scan>
使用@Autowired自动装配Bean
一般情况下,所有使用@Autowired注解的属性都要被设置,当Spring找不到匹配的Bean时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired 注解的 required 属性 为fasle。
默认情况下,当IOC容器里存在多个类型兼容的 Bean 时,通过类型的自动装配将无法工作,此时可以在 @Qualifier 注解里提供 Bean 的名称,Spring 允许对方法的形参标注 @Qualifier 以指定注入 Bean 的名称。
--@Autowired 注解也可以应用在 数组类型 的属性上,此时Spring 会把所有匹配的 Bean 进行自动装配。
--@Autowired 注解也可以应用在 集合属性 上,此时Spring 读取该集合的类型信息,然后自动装配所有与之兼容的 Bean。
--@Autowired 注解用在 java.util.Map 上时,若该 Map 的键值为 String ,那么 Spring 将自动装配与之 Map 值类型兼容的 Bean ,此时Bean 的名称作为键值。
21.泛型依赖输入
public class BaseService<T> {
@Autowired
private BaseRepository<T> baseRepository;
public void add(){
System.out.println("add...");
System.out.println(baseRepository);
}
}
@Service
public class UserService extends BaseService<User>{
}
@Repository
public class UserRepository extends BaseRepository<User>{
}
当 userService 调用 add 方法时,会输出
add...
com.spring.beeans.generic.di.UserRepository@2449a2da
22.动态配置(AOP基础):
public class ArithmeticCalculatorLoggingProxy {
//要代理的对象
private ArithmeticCalculator target;
public ArithmeticCalculatorLoggingProxy (ArithmeticCalculator target) {
this.target=target;
}
public ArithmeticCalculator getLoggingProxy(){
//要代理的对象
ArithmeticCalculator proxy ;
//代理对象由哪一个类加载器负责加载
ClassLoader loader= target.getClass().getClassLoader();
//代理对象的类型,即其中有哪些方法
Class[] interfaces=new Class[]{ArithmeticCalculator.class};
//当调用代理对象其中的方法时,该执行的代码
InvocationHandler h=new InvocationHandler() {
@Override
/*
* proxy:正在返回的那个代理对象,一般情况下,在 invoke 方法中都不使用该对象
* method:正在被调用的方法
* args:调用方法时,传入的参数
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("invoke...");
//日志
System.out.println("The method "+method.getName()+" begins with "+Arrays.asList(args));
//执行方法
Object result=method.invoke(target, args);
//日志
System.out.println("The method "+method.getName()+" ends with "+result);
return result;
}
};
proxy=(ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
public int add(int i, int j) {
return i+j;
}
public int sub(int i, int j) {
// TODO Auto-generated method stub
return i-j;
}
public int mul(int i, int j) {
// TODO Auto-generated method stub
return i*j;
}
public double div(double i, double j) {
return i/j;
}
}
public class Main {
public static void main(String[] args) {
ArithmeticCalculator target=new ArithmeticCalculatorImpl();
ArithmeticCalculator proxy=new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();
System.out.println(proxy.getClass().getName());
int result=proxy.add(1, 2);
System.out.println(result);
result=proxy.sub(3, 1);
System.out.println(result);
}
}
输出结果为:
com.sun.proxy.$Proxy0
invoke...
The method add begins with [1, 2]
The method add ends with 3
3
invoke...
The method sub begins with [3, 1]
The method sub ends with 2
2
23.(1)SpringAOP
①加入JAR包 ②在配置文件中加入 aop 的命名空间
③基于注解的方式:
i.在配置文件中加入如下配置:
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean class="Aspect.class" / >
<!--扫描AOP和代理对象的类-->
<context:component-scan base-package="com.aop" />
AOP类:
@Aspect
public class LogginPerformance {
@Pointcut("execution(** com.aop.Performance.perform(..))")
public void cut() {}
@Before("cut()")
public void beforeMethod() {
System.out.println("Before");
}
}
代理对象类:
package com.aop;
public interface Performance {
public void perform();
}
还需要讲implements 该接口类的 类 加入扫描对象
package com.aop;
@Component
public class Singer implements Performance{
@Override
public void perform() {
System.out.println("唱歌");
}
}
使用方法:
package com.aop;
@Component
public class TestAOP {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
Performance p=ctx.getBean(Performance.class);
p.perform();
}
}