<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-web --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> </dependencies>
1.使用无参构造创建对象,默认!
2.假设我们要使用有参构造创建对象。
1.下标赋值 Constructor argument index
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </bean>
2.类型(不推荐)Constructor argument type matching
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>
3.直接通过参数名 Constructor argument index
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg name="years" value="7500000"/> <constructor-arg name="ultimateAnswer" value="42"/> </bean>
总结:在配置文件加载的时候,容器中的管理对象就已经初始化了!
<!--别名,如果添加了别名,我们也可以使用别名获取这个对象-->
<alias name="user" alias="userNew"/>
id:bean 的唯一表示标识符,也就是相当于我们学的对象名
class:bean 对象所对应的全限定名:包名+类型
name:也是别名,而且name,可以同时取多个别名
<bean id="exampleBean" class="examples.ExampleBean" name="user1 us,22 11"/>
这个imort,一般用于团队开发,他可以将多个配置文件,导入合并为一个
假设,现在项目中 有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
<import resource="beans.xml"/> <import resource="bean1.xml"/> <import resource="bean2.xml"/>
前面的
<bean id="moreComplexObject" class="example.ComplexObject"> <!-- results in a setAdminEmails(java.util.Properties) call --> <property name="adminEmails"> <props> <prop key="administrator">administrator@example.org</prop> <prop key="support">support@example.org</prop> <prop key="development">development@example.org</prop> </props> </property> <!-- results in a setSomeList(java.util.List) call --> <property name="someList"> <list> <value>a list element followed by a reference</value> <ref bean="myDataSource" /> </list> </property> <!-- results in a setSomeMap(java.util.Map) call --> <property name="someMap"> <map> <entry key="an entry" value="just some string"/> <entry key ="a ref" value-ref="myDataSource"/> </map> </property> <!-- results in a setSomeSet(java.util.Set) call --> <property name="someSet"> <set> <value>just some string</value> <ref bean="myDataSource" /> </set> </property> </bean>
例如创建一个环境
package com.kai.z; public class demo1 { private String name; private String sex; private int age; private String address; @Override public String toString() { return "demo1{" + "名字='" + name + '\'' + ", 性别='" + sex + '\'' + ", 年龄=" + age + ", 地址='" + address + '\'' + '}'; } public void add(int a, int b){ System.out.println(a+b); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
在bean容器中注入参数:
<bean id="demo1" class="com.kai.z.demo1"> <property name="name" value="赵智"/> <property name="address" value="南宁"/> <property name="age" value="20"/> <property name="sex" value="男"/> </bean>
beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="john-classic" class="com.example.Person"> <property name="name" value="John Doe"/> <property name="spouse" ref="jane"/> </bean> <bean name="john-modern" class="com.example.Person" p:name="John Doe" p:spouse-ref="jane"/> <bean name="jane" class="com.example.Person"> <property name="name" value="Jane Doe"/> </bean> </beans>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="classic" class="com.example.ExampleBean"> <property name="email" value="someone@somewhere.com"/> </bean> <bean name="p-namespace" class="com.example.ExampleBean" p:email="someone@somewhere.com"/> </beans>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="beanTwo" class="x.y.ThingTwo"/> <bean id="beanThree" class="x.y.ThingThree"/> <!-- traditional declaration with optional argument names --> <bean id="beanOne" class="x.y.ThingOne"> <constructor-arg name="thingTwo" ref="beanTwo"/> <constructor-arg name="thingThree" ref="beanThree"/> <constructor-arg name="email" value="something@somewhere.com"/> </bean> <!-- c-namespace declaration with argument names --> <bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo" c:thingThree-ref="beanThree" c:email="something@somewhere.com"/> </beans>
p命名空间注入,可直接注入属性的值:property
c命名空间注入,通过构造器注入:construct-args
注意点:p命名和c命名空间不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
Scope |
Description |
singleton |
(Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype |
Scopes a single bean definition to any number of object instances. |
request |
Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
session |
Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
application |
Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
websocket |
Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
1、单例模式(Spring默认机制)
<bean id="accountService" class="com.something.DefaultAccountService"/> <!-- the following is equivalent, though redundant (singleton scope is the default) --> <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
2、原型模式(每次从容器中get的时候,都会产生新的对象)---多线程时使用
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
3、其余的request,session,application这些只能在web开发中使用到
*Spring会在上下文中自动寻找,并自动给bean装配属性
*自动装配时Spring满足bean依赖的一种方式!
在Spring中有三种装配的方式
1、在xml中显示的配置
2、在java中配置
3、隐式的自动装配bean【重要】
1、搭建环境
例如:一个人有两只宠物
package com.zzk.pojo; public class Pepole { private Cat cat; private Dog dog; private String name; public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
普通的装配:
<bean id="cat" class="com.zzk.pojo.Cat"/> <bean id="dog" class="com.zzk.pojo.Dog"/> <bean id="p" class="com.zzk.pojo.Pepole"> <property name="name" value="赵"/> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> </bean>
<bean id="cat" class="com.zzk.pojo.Cat"/> <bean id="dog" class="com.zzk.pojo.Dog"/> <!-- byName:会自动在容器上下文中查找,和自己对象set方法后面的对应值 bean id --> <bean id="p" class="com.zzk.pojo.Pepole" autowire="byName"> <property name="name" value="赵"/> </bean>
<bean id="cat" class="com.zzk.pojo.Cat"/> <bean id="dog" class="com.zzk.pojo.Dog"/> <!-- byName:会自动在容器上下文中查找,和自己对象set方法后面的对应值 bean id byType:会自动在容器上下文中查找,和自己对象类型相同的 bean --> <bean id="p" class="com.zzk.pojo.Pepole" autowire="byType"> <property name="name" value="赵"/> </bean>
小结:
*byname的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!
*bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
jdk1.5支持的注解,Spring2.5就支持注解了!
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.
要使用注解须知:
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
@Autowired
直接在属性上使用即可,也可以在set方式上使用
使用Autowired我们可以不用编写set方法了,前提是这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byname!
package com.zzk.pojo; import org.springframework.beans.factory.annotation.Autowired; public class Pepole { @Autowired private Cat cat; @Autowired private Dog dog; private String name; public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <bean id="cat" class="com.zzk.pojo.Cat"/> <bean id="dog" class="com.zzk.pojo.Dog"/> <bean id="p" class="com.zzk.pojo.Pepole" > </bean> </beans>
科普:
@Nullable 字段标记了这个注解,说明这字段可以为null
@Autowired的require属性默认为ture。
public @interface Autowired { boolean required() default true; }
如果显示定义了Autowired的require属性为false,说明这个对象可以为null,否则不能为空。
@Autowired(required = false) private Cat cat; @Autowired private Dog dog;
strong>如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【</strongstrong>@Autowired</strong/span><strong>】完成的时候,可以通过使用@Qualifier(value="xxx")去配置</strongstrong>@Autowired的使用,指定一个唯一的bean对象注入!</strong
<bean id="cat" class="com.zzk.pojo.Cat"/> <bean id="cat2" class="com.zzk.pojo.Cat"/> <bean id="dog" class="com.zzk.pojo.Dog"/> <bean id="dog2" class="com.zzk.pojo.Dog"/> <bean id="p" class="com.zzk.pojo.Pepole" > </bean>
使用@Qualifier(value="xxx")
@Autowired @Qualifier(value = "cat2") private Cat cat; @Autowired @Qualifier(value = "dog2") private Dog dog;
还有一个@Resource,java原生的自动装配,在Jdk11中被移除了。这里就不讲了。。
*@Autowired 通过byType的方式实现,而且必须要求这个对象存在【常用】
*@Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就会报错。。
在Spring4之后,要使用注解开发,必须要保证aop的包导入了。
使用注解需要导入context约束,增加注解的支持
1. bean
2.属性如何注入
package com.zzk.pojo; import org.springframework.stereotype.Component; //@Component 注解 等价于 <bean id="user" class="com.zzk.pojo.User"/> @Component public class User { public String name="赵智"; }
package com.zzk.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class User { @Value("赵智")//相当于<property name="name" value="赵智"/> public String name; }
package com.zzk.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class User { public String name; @Value("赵智")//相当于<property name="name" value="赵智"/> public void setName(String name) { this.name = name; } }
有以上三种
3.衍生的注解
@Component 有几个衍生注解,在web开发中,会按照mvc三层架构分层
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配bean
4.自动装配置
*@Autowired 通过byType的方式实现,而且必须要求这个对象存在【常用】
*@Nullable 字段标记了这个注解,说明这字段可以为null
*@Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就会报错。。
*@Component:注解,放类上说明这个类被Spring管理了。
5作用域
单例模式:
@Scope("singleton")
原型模式:
@Scope("prototype")
6.小结
xml与注解:
*xml 更加万能,适用于任何场合,维护简单方便
*注解 不是自己类使用不了,维护相对复杂!
最佳实践:
*xml 用来管理bean
*注解 只用来完成属性的注入
*我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<!--指定要扫描的包,这个包下的注解就会生效--> <context:component-scan base-package="com.zzk"/> <context:annotation-config/>
完全不适用Spring的xml配置,全权交给java来做!
JavaConfig是Spring的一个子项目,在Spring 4之后成为了一个核心功能。
实体类:
package com.zzk.app; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; //交给Spring容器接管,注册到容器中 @Componet public class User { @Value("赵智")//注入属性 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
配置类:
package com.zzk.config; import com.zzk.app.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; //@Configuration代表这是一个配置类,就是和beans.xml是一样的 //也会放到spring容器中托管,本身就是@Component @Configuration //扫描包 @ComponentScan("com.zzk") //@Import 相当于导入新的一个xml @Import(Config2.class) public class Appconfig { //注册一个bean,相当于写的一个bean标签 //这个方法的名字就相当于bean标签中的id属性 //这个方法的返回值就相当于bean标签中的class属性 @Bean public User getuser(){ return new User();//就是要注入到bean中的对象 } }
测试类:
import com.zzk.app.User; import com.zzk.config.Appconfig; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Mytest { public static void main(String[] args) { //如果完全使用了配置类方式去做,只能通过 AnnotationConfig 上下文来获取容器,通过配置类的class对象加载 ApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class); User getuser = (User) context.getBean("getuser"); System.out.println(getuser.getName()); } }
这种纯java的配置方式,在SpringBoot中随处可见!
代理模式就是SpringAOP的底层。
代理模式的分类:
*静态代理
*动态代理
角色分析:
*抽象角色:一般会使用接口或者抽象类来解决
*真实角色:被代理的角色
*代理角色:代理真实角色,代理真实角色后,一般会做一些附属操作
*客户:访问代理对象的人
代码步骤:
1.接口
package com.zzk.demo1; //出租房子 public interface Rent { void rent(); }
2.真实角色
package com.zzk.demo1; //房东 public class Host implements Rent { public void rent() { System.out.println("房东要出租房子"); } }
3.代理角色
package com.zzk.demo1; //代理 public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } public void rent() { host.rent(); hetong(); fee(); } public void fee(){ System.out.println("中介费"); } public void hetong(){ System.out.println("合同"); } }
4.客户端访问代理角色
package com.zzk.demo1; public class Buy { public static void main(String[] args) { //房东出租房子 Host host = new Host(); //代理 Proxy proxy = new Proxy(host); //不用找房东,租房找代理 proxy.rent(); } }
代理模式的好处:
缺点:
代码:10-6
AOP
1.基于接口---JDK 动态代理【这里要用的】
2.基于类---cglib
3.java字节码实现:javassist
需要了解两个大类:proxy:代理,invocationhandler:调用处理
动态代理的好处:
ProxyInvocationHandler类,写死的,一个工具类:
package com.zzk.demo2; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Object target; public void setTarget(Object target) { this.target = target; } //生成得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //处理代理实例,并返回结果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //动态代理的本质就是使用反射机制实现的 Object result = method.invoke(target,args); log(method.getName());//实现额外方法 return result; } //这里就可以写额外方法 public void log(String msg){ System.out.println("使用了"+msg+"方法"); } }
Client类:
package com.zzk.demo2; public class Client { public static void main(String[] args) { //真实角色 UserServiceImpl ss = new UserServiceImpl(); //代理角色,不存在的 ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setTarget(ss);//设置要代理的对象 //动态生成代理类 UserService proxy = (UserService) pih.getProxy(); proxy.query(); } }
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译的方式和运行期间动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
提供声明式事务:允许用户自定义切面
【重点】使用AOP的织入,需要导入一个依赖包
<dependencies> <!-- https://mvnrepository. com/artifact/org. aspectj/aspectjweaver --><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies>
方式一:使用Spring接口【主要是SpringAPI接口实现】
log类:
package com.zzk.demo3; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; //前置 public class Log implements MethodBeforeAdvice { //method:要执行目标对象的方法 //object:参数 //o:目标对象 @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(o.getClass().getName()+"的"+method.getName()+"方法"); } }
loga类:
package com.zzk.demo3; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; //这个类是后置类,程序结束时运行 public class Loga implements AfterReturningAdvice { //returnValue:返回值 @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了(这是尾巴)"+"返回结果为:"+returnValue); } }
UserServiceImpl类:
package com.zzk.demo3; public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("增"); } @Override public void delete() { System.out.println("删"); } @Override public void update() { System.out.println("改"); } @Override public void query() { System.out.println("查"); } }
ApplicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--注册beans--> <bean id="userservice" class="com.zzk.demo3.UserServiceImpl"/> <bean id="log" class="com.zzk.demo3.Log"/> <bean id="loga" class="com.zzk.demo3.Loga"/> <!--方式一:使用原生Spring API接口--> <!--配置aop,需要导入aop的约束--> <aop:config> <!--切入点:expression:表达式,execution(要执行的位置!* * * * *) --> <aop:pointcut id="pointcut" expression="execution(* com.zzk.demo3.UserServiceImpl.*())"/> <!--环绕增加--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="loga" pointcut-ref="pointcut"/> </aop:config> </beans>
方式二:自定义来实现AOP【主要是切面定义】
自定义Diy类:
package com.zzk.diy; public class Diy { public void before(){ System.out.println("=======头部======"); } public void after(){ System.out.println("=======尾巴======"); } }
xml中:
<!--方式二:自定义类--> <bean id="diy" class="com.zzk.diy.Diy"/> <aop:config> <!--自定义切面,ref:要引用的类--> <aop:aspect ref="diy"> <!--切入点 *号后面表类中所有的方法--> <aop:pointcut id="point" expression="execution(* com.zzk.demo3.UserServiceImpl.*(..))"/> <!--通知--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
方式三:使用注解实现
AnnotationPointcut类中:
ackage com.zzk.diy; //方式三:使用注解方式实现AOP import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect//标注这个类是一个切面 public class AnnotationPointcut { //Before注解相当于 <aop:before method="before" pointcut-ref="point"/> //execution为切入点 @Before("execution(* com.zzk.demo3.UserServiceImpl.*(..))") public void before(){ System.out.println("=======方法执行前======="); } }
xml中:
<!--方式三--> <bean id="annotationPointcut" class="com.zzk.diy.AnnotationPointcut"/> <!--开启注解支持。--> <aop:aspectj-autoproxy/>
待...
标签: 开发日记